到POCO类添加属性在运行时(Add property to POCO class at runti

2019-07-18 11:15发布

我选择ServiceStack OrmLite为我的项目是一个纯粹的面向数据的应用程序。 我愿意允许最终用户创建的,将被用来生成使用在运行时类中的XML格式定义自己的对象类型的CodeDOM 。

我也将定义应用程序(即需要进行一些“系统”对象User ),但我不能预见所有的最终用户将使用属性,因此,我正在寻找一种方式,让延长我在设计时创建的类。 样品波纹管

public class User
{
    public Guid Uid { get; set; }
    public String Username { get; set; }
    public String Password { get; set; }
}

最终用户希望有一个EmailAddress 。 他应该能在2个属性添加到上层阶级和全类将(仍然可以通过使用OrmLite,因为它可以覆盖:

public class User
{
    public Guid Uid { get; set; }
    public String Username { get; set; }
    public String Password { get; set; }
    public String Email{ get; set; }
    public String Address { get; set; }
}

我知道有可能这样做使系统崩溃(如果类已经实例化),所以我要寻找避免这个问题,并模仿需要我的最佳方式的风险。

Answer 1:

它似乎有两个部分你在做什么这里。 您需要动态地创建类型,以支持额外的属性。 你还需要确保不会出现重复的类型在你的AppDomain,即两个不同的定义User

运行时类型代

已经给出了各种建议处理如何创建类型。 在一个项目中,我们有类似的东西。 我们创建了一个基类,有核心性能和存储“扩展”性质的字典。 然后,我们使用Reflection.Emit创建派生类型具有良好的特性。 每个属性的定义简单地读或写在基类的字典。 由于Reflection.Emit需要编写低级别的IL代码,它起初看似复杂。 我们在其他类库中写了一些样品派生类和编译他们。 这些是什么,我们会实际需要,以实现在运行时的例子。 然后,我们使用程序Ildasm.exe看到编译器产生什么代码。 这使得它很容易找出我们如何能够在运行时生成相同的代码。

避免命名空间冲突

你的第二个挑战是避免有重复的类型名。 我们追加一个GUID(含无效字符删除),以每个生成类型的名称,以确保这从来没有发生过。 简单的办法,虽然我不知道你是否能逃脱与您的ORM。

如果这是服务器代码,您还需要考虑的是,组件从未在.NET卸载。 因此,如果你反复在运行时产生新的类型,你的进程将继续增长。 同样将在客户端代码中发生的,但如果你不希望的过程,对于长时间运行,这可能是问题不大。

我说的组件不卸载; 但是,您可以卸载整个AppDomain 。 因此,如果这是服务器端的代码,你可以在自己的应用程序域整个操作运行,然后撕裂下来之后,以确保动态创建的类型被卸载。



Answer 2:

为什么不使用其所有属性键值对,或者至少是动态的?

http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx

你可以做你与反思描述的方式,但它会采取的性能损失,这种方式将允许除去性能也。



Answer 3:

我目前工作的项目也有类似的要求。 我们已经有一个系统在生产中,有一个客户端请求另外的字段。

我们通过简单地增加一个CustomFields属性,我们的模型解决了这个。

public class Model: IHasId<Guid>
{
    [PrimaryKey]
    [Index(Unique = true)]
    public Guid Id { get; set; }

    // Other Fields...

    /// <summary>  
    /// A store of extra fields not required by the data model.  
    /// </summary>  
    public Dictionary<string, object> CustomFields { get; set; }  
}

我们已经使用了这个没有问题了几个星期。

我们从这个发现的另外一个好处是,每行可以有自己的自定义字段,这样我们就可以在每记录的基础处理他们,而不是要求他们对每条记录的。



Answer 4:

退房ExpandoObject ,它提供了做这样的动态语言支持。 您可以使用它在运行时的附加属性您POCO的补充。 下面是使用.NET的DLR功能的链接: http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28v=vs.100%29.aspx



文章来源: Add property to POCO class at runtime