动态代理:包装构造函数

发布于 2024-12-12 09:30:49 字数 2369 浏览 0 评论 0原文

我正在尝试为另一种类型的数据提供程序(ESRI 地理数据库,使用 ESRI .NET 库)创建 Active Record 实现(我了解 Castle 的计划,它非常好),并且我得到了一些有趣的结果。

尽管如此,我还是有一个问题。我的 ActiveRecord 类如下所示:

public interface IActiveRecord<T> : IActiveRecord where T : class
{
    T Create();
    void Update(T record);
    void Delete(T record);
}

public interface IActiveRecord
{
    int ObjectId { get; set; }
    bool Managed { get; }
    bool IsValid { get; }

    IObject EsriObject { get; set; }

    IGeometry Geometry { get; set; }

    void Save();
    void Delete();
}

我有静态 Create 方法,该方法转到 DynamicProxy 并为我生成一个代理。但是我如何强制为继承类生成的实例也被代理呢?

public class ActiveRecord<T> : IActiveRecord where T : IActiveRecord,new()
{

    //  protected constructors

    public static T Create(IObject obj)
    {
        var record = Create();
        record.EsriObject = obj;
        return (T)record;
    }
}

// inherited class
[Workspace(@"C:\teste.gdb")]
[Table("TB_PARCEL",Geometry=esriGeometryType.esriGeometryPolygon)]
public class Parcel : ActiveRecord<Parcel>,IParcel
{
    [Field(4, "NM_PARCEL_ID", esriFieldType.esriFieldTypeString)]
    public virtual string ParcelId { get; set; }

    [Field(5, "NR_PARCEL_NO", esriFieldType.esriFieldTypeInteger)]
    public virtual int StreetNumber { get; set; }
    public virtual IOwner ParcelOwner { get; set; }
}

看看测试。前三个测试照常被拦截,但第四个测试则不会。我需要 A) 阻止用户实例化它自己的类(在我看来,对于 API 来说这是不好的方法),或者找到一种从继承的类构造函数返回代理的方法。

    [TestMethod]
    public void ActiveRecordConstructor()
    {
        Parcel p1 = Parcel.Create();
        Assert.IsFalse(p1.Managed);
        Assert.AreEqual(null, p1.ParcelId);

        Parcel p2 = Parcel.Create(2);
        Assert.IsFalse(p2.Managed);

        IObject fake = _repository.StrictMock<IObject>();

        using (_repository.Record())
        {
            fake.Stub(x => x.get_Value(4)).Return("teste");
        }

        using (_repository.Playback())
        {
            Parcel p3 = Parcel.Create(fake);
            Assert.IsTrue(p3.Managed);
            Assert.AreEqual("teste", p3.ParcelId);
        }

        // this wont be intercepted
        Parcel p4 = new Parcel();
        Assert.IsFalse(p4.Managed);
        Assert.IsNull(p4.ParcelId);
    }

简而言之,我需要每当用户创建一个新的 Class() 时,它都会返回一个代理对象。在允许继承的情况下这可能吗?

谢谢!

I'm taking a stab at creating a Active Record implementation (I know about Castle's initiative, and it's very good) for another type of data provider (ESRIs geodatabases, using ESRIs .NET libraries) and I'm reaching something interesting.

I have a question nevertheless. I have my ActiveRecord classes which is like this:

public interface IActiveRecord<T> : IActiveRecord where T : class
{
    T Create();
    void Update(T record);
    void Delete(T record);
}

public interface IActiveRecord
{
    int ObjectId { get; set; }
    bool Managed { get; }
    bool IsValid { get; }

    IObject EsriObject { get; set; }

    IGeometry Geometry { get; set; }

    void Save();
    void Delete();
}

I have static Create methods, which go to DynamicProxy and generate me a proxy. But how I can enforce that the instance generated for a inheriting class is proxied too?

public class ActiveRecord<T> : IActiveRecord where T : IActiveRecord,new()
{

    //  protected constructors

    public static T Create(IObject obj)
    {
        var record = Create();
        record.EsriObject = obj;
        return (T)record;
    }
}

// inherited class
[Workspace(@"C:\teste.gdb")]
[Table("TB_PARCEL",Geometry=esriGeometryType.esriGeometryPolygon)]
public class Parcel : ActiveRecord<Parcel>,IParcel
{
    [Field(4, "NM_PARCEL_ID", esriFieldType.esriFieldTypeString)]
    public virtual string ParcelId { get; set; }

    [Field(5, "NR_PARCEL_NO", esriFieldType.esriFieldTypeInteger)]
    public virtual int StreetNumber { get; set; }
    public virtual IOwner ParcelOwner { get; set; }
}

Take a look at the tests. The first three tests get intercepted as usual, but not the fourth test. I need A) prevent the user from instancing it's own classes (bad approach for the API in my opinion) or find a way to return from the inherited classes constructors the proxies.

    [TestMethod]
    public void ActiveRecordConstructor()
    {
        Parcel p1 = Parcel.Create();
        Assert.IsFalse(p1.Managed);
        Assert.AreEqual(null, p1.ParcelId);

        Parcel p2 = Parcel.Create(2);
        Assert.IsFalse(p2.Managed);

        IObject fake = _repository.StrictMock<IObject>();

        using (_repository.Record())
        {
            fake.Stub(x => x.get_Value(4)).Return("teste");
        }

        using (_repository.Playback())
        {
            Parcel p3 = Parcel.Create(fake);
            Assert.IsTrue(p3.Managed);
            Assert.AreEqual("teste", p3.ParcelId);
        }

        // this wont be intercepted
        Parcel p4 = new Parcel();
        Assert.IsFalse(p4.Managed);
        Assert.IsNull(p4.ParcelId);
    }

In short I need that whenever a user creates a new Class(), it returns a proxied object. Is that possible while allowing inheritance?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

屌丝范 2024-12-19 09:30:50

DynamicProxy 无法拦截对构造函数的调用。它必须控制对象的创建。

DynamicProxy cannot intercept calls to constructors. It has to control the creation of the object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文