在运行时将属性添加到POCO类

时间:2013-01-20 00:23:42

标签: c# properties runtime poco ormlite-servicestack

我为我的项目选择了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; }
}

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

4 个答案:

答案 0 :(得分:4)

看来你在这里做的事情有两个部分。您需要动态创建类型以支持其他属性。您还需要确保在AppDomain中永远不会出现重复类型,即User的两种不同定义。

运行时类型生成

已经给出的各种建议处理如何创建类型。在一个项目中,我们有类似的东西。我们创建了一个具有核心属性的基类和一个用于存储“扩展”属性的字典。然后我们使用Reflection.Emit来创建具有所需属性的派生类型。每个属性定义只是从基类中的字典读取或写入。由于Reflection.Emit需要编写低级IL代码,因此最初看起来很复杂。我们在另一个类库中编写了一些示例派生类并对其进行了编译。这些是我们在运行时实际需要实现的示例。然后我们使用ildasm.exe来查看编译器生成的代码。这使得我们可以很容易地弄清楚如何在运行时生成相同的代码。

避免命名空间冲突

您的第二个挑战是避免重复的类型名称。我们将guid(删除了无效字符)附加到每个生成类型的名称,以确保从未发生过。很容易解决,但我不知道你是否可以通过你的ORM来解决这个问题。

如果这是服务器代码,您还需要考虑在.NET中永远不卸载程序集的事实。因此,如果您在运行时重复生成新类型,您的流程将继续增长。客户端代码也会发生同样的情况,但如果您不希望该进程长时间运行,则可能不会出现问题。

我说装配没有卸下;但是,您可以卸载整个AppDomain。因此,如果这是服务器代码,您可以在其自己的appdomain中运行整个操作,然后将其拆除以确保卸载动态创建的类型。

答案 1 :(得分:0)

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

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

你可以按照你用Reflection描述的方式来实现,但它会受到性能影响,这种方式也可以删除属性。

答案 2 :(得分:0)

我目前正在开展的项目有类似的要求。我们的系统已经投入生产,并且有一个客户请求添加字段。

我们通过简单地向我们的模型添加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; }  
}

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

我们从中发现的另一个好处是每行可以有自己的自定义字段,因此我们可以按记录处理它们,而不是每条记录都需要它们。

答案 3 :(得分:0)

查看ExpandoObject,它为执行此类操作提供动态语言支持。您可以使用它在运行时向POCO添加其他属性。以下是使用.NET的DLR功能的链接:http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28v=vs.100%29.aspx