通用一个类来处理多种类型

时间:2010-10-08 15:51:45

标签: c#

我的数据库模式中有一系列大约30个查找表,它们都具有相同的布局(我宁愿将它们保存为单独的表而不是一个查找表),因此我的Linq2SQL上下文有30个实体用于这些查找表。

我有一个标准类,我将用于这30个实体中的每一个的CRUD操作,例如:

public class ExampleAttributes : IAttributeList
{
    #region IAttributeList Members

    public bool AddItem(string Item, int SortOrder)
    {
        MyDataContext context = ContextHelper.GetContext();
        ExampleAttribute a = new ExampleAttribute();
        a.Name = Item;
        a.SortOrder = SortOrder;
        context.ExampleAttributes.InsertOnSubmit(a);

        try
        {
            context.SubmitChanges();
            return true;
        }
        catch
        {
            return false;
        }
    }

    public bool DeleteItem(int Id)
    {
        MyDataContext context = ContextHelper.GetContext();

        ExampleAttribute a = (from m in context.ExampleAttributes
                            where m.Id == Id
                            select m).FirstOrDefault();

        if (a == null)
            return true;

        // Make sure nothing is using it
        int Count = (from m in context.Businesses
                             where m.ExampleAttributeId == a.Id
                             select m).Count();

        if (Count > 0)
            return false;

        // Delete the item
        context.ExampleAttributes.DeleteOnSubmit(a);

        try
        {
            context.SubmitChanges();
            return true;
        }
        catch
        {
            return false;
        }
    }

    public bool UpdateItem(int Id, string Item, int SortOrder)
    {
        MyDataContext context = ContextHelper.GetContext();

        ExampleAttribute a = (from m in context.ExampleAttributes
                            where m.Id == Id
                            select m).FirstOrDefault();

        a.Name = Item;
        a.SortOrder = SortOrder;

        try
        {
            context.SubmitChanges();
            return true;
        }
        catch
        {
            return false;
        }
    }

    public String GetItem(int Id)
    {
        MyDataContext context = ContextHelper.GetContext();
        var Attribute = (from a in context.ExampleAttributes
                         where a.Id == Id
                         select a).FirstOrDefault();

        return Attribute.Name;
    }

    public Dictionary<int, string> GetItems()
    {
        Dictionary<int, string> Attributes = new Dictionary<int, string>();

        MyDataContext context = ContextHelper.GetContext();
        context.ObjectTrackingEnabled = false;

        Attributes = (from o in context.ExampleAttributes orderby o.Name select new { o.Id, o.Name }).AsEnumerable().ToDictionary(k => k.Id, v => v.Name);

        return Attributes;
    }

    #endregion
}

我可以复制这个类30次,每个查找实体都进行了很小的更改,但这看起来很麻烦 - 所以这个类可以通用化,所以我也可以传递它我想要的类型,并让它在内部处理类型差异在linq查询?这样,我有一个类可以添加,一个类可以修复bug等 - 似乎应该这样做。

更新

安德鲁斯在下面的回答给了我一个选项,我在考虑这个问题(传递类型)时真的在看,但我需要更多关于如何对linq查询进行泛化的说明。任何人都可以澄清这个吗?

干杯

4 个答案:

答案 0 :(得分:1)

您可以尝试一些事情。

一种是定义一个接口,该接口具有三十个实体类共享的所有相关字段。然后,您可以通过执行类似

之类的操作让每个实体类实现此接口(让我们称之为IMyEntity
public partial class EntityNumber1 : IMyEntity
{
}

表示每个实体(其中EntityNumber1是其中一个实体类的名称)。当然,这仍然是三十个不同的定义,但是你的CRUD操作类可以在IMyEntity上运行,而不必每次都写一个新类。

第二种方法是简单地按照你的建议对CRUD操作类进行泛化:

public class ExampleAttributes<T> : IAttributeList
{
    ...

允许您使用T作为操作类型。当然,与第一种方法结合使用可能更容易,因为您仍然需要检查属性的存在并将实体强制转换为适当的类型或接口。

修改

要检查实体是否存在适当的属性,您可能需要使用反射方法。检查给定类型T是否具有特定属性的一种方法可能是检查

typeof(T).GetProperties().OfType<PropertyInfo>().Count<PropertyInfo>(pi => pi.Name == "MyPropertyName" && pi.GetGetMethod().ReturnType == typeof(TypeIWant)) > 0

当然,将TypeIWant替换为您期望该属性的类型,并将MyPropertyName替换为您要检查的属性的名称。

答案 1 :(得分:0)

向构造函数添加一个参数,指定类型。然后你可以在内部使用它。一个类,在构造函数中可能有一个switch语句。

答案 2 :(得分:0)

对于LINQ查询的通用化,最大的问题是您的DataContext具有基于类型的集合。有几种方法可以避免这种情况。您可以尝试使用反射来访问它,但这需要相当多的黑客攻击,并且几乎会破坏LINQ to SQL将提供的所有效率。

最简单的方法似乎是使用Dynamic LINQ。我没有亲自使用它,但它似乎应该支持它。您可以在此主题中找到更多信息:Generic LINQ query predicate?http://aspalliance.com/1569_Dynamic_LINQ_Part_1_Using_the_LINQ_Dynamic_Query_Library.1上 也许其他人可以提供更多相关信息?

答案 3 :(得分:0)

这不一定是问题的答案,但可能是您问题的解决方案。您是否考虑过生成所需的所有课程? T4内置于Visual Studio中,可以为您生成代码。下面的链接相当广泛地描述了它,但包含大量链接以获取更多信息。

http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

这样,您可以在一个地方定义所有方法,并为30多个查找模型生成类文件。一个地方做出改变等。

也许值得考虑,如果没有,仍然值得了解。