C# 泛化一个类以处理多个类型
我的数据库模式中有一系列大约30个查找表,它们都具有相同的布局(我更愿意将它们作为单独的表而不是一个查找表),因此我的Linq2SQL上下文中有30个实体用于这些查找表 我有一个标准类,用于这30个实体的CRUD操作,例如:C# 泛化一个类以处理多个类型,c#,C#,我的数据库模式中有一系列大约30个查找表,它们都具有相同的布局(我更愿意将它们作为单独的表而不是一个查找表),因此我的Linq2SQL上下文中有30个实体用于这些查找表 我有一个标准类,用于这30个实体的CRUD操作,例如: public class ExampleAttributes : IAttributeList { #region IAttributeList Members public bool AddItem(string Item, int SortOrder)
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
}
公共类示例属性:IAttributeList
{
#地区论坛成员
公共bool AddItem(字符串项,整数排序器)
{
MyDataContext=ContextHelper.GetContext();
ExampleAttribute=新的ExampleAttribute();
a、 名称=项目;
a、 SortOrder=SortOrder;
context.ExampleAttributes.InsertOnSubmit(a);
尝试
{
context.SubmitChanges();
返回true;
}
抓住
{
返回false;
}
}
公共布尔删除项(内部Id)
{
MyDataContext=ContextHelper.GetContext();
ExampleAttribute=(来自context.ExampleAttributes中的m
其中m.Id==Id
选择m).FirstOrDefault();
如果(a==null)
返回true;
//确保没有任何东西在使用它
int Count=(来自context.business中的m)
其中m.ExampleAttributeId==a.Id
选择m.Count();
如果(计数>0)
返回false;
//删除该项目
context.ExampleAttributes.DeleteOnSubmit(a);
尝试
{
context.SubmitChanges();
返回true;
}
抓住
{
返回false;
}
}
公共bool UpdateItem(int-Id、字符串项、int-SortOrder)
{
MyDataContext=ContextHelper.GetContext();
ExampleAttribute=(来自context.ExampleAttributes中的m
其中m.Id==Id
选择m).FirstOrDefault();
a、 名称=项目;
a、 SortOrder=SortOrder;
尝试
{
context.SubmitChanges();
返回true;
}
抓住
{
返回false;
}
}
公共字符串GetItem(int Id)
{
MyDataContext=ContextHelper.GetContext();
var Attribute=(来自context.ExampleAttributes中的
其中a.Id==Id
选择一个.FirstOrDefault();
返回属性.Name;
}
公共字典GetItems()
{
字典属性=新字典();
MyDataContext=ContextHelper.GetContext();
context.ObjectTrackingEnabled=false;
Attributes=(从context.ExampleAttributes orderby o.Name选择new{o.Id,o.Name}).AsEnumerable().ToDictionary(k=>k.Id,v=>v.Name);
返回属性;
}
#端区
}
我可以将这个类复制30次,对每个查找实体进行非常小的更改,但这似乎有点混乱-所以这个类可以被泛化,以便我也可以传递我想要的类型,并让它在内部处理linq查询中的类型差异吗?这样的话,我有一个类要添加,一个类要修复bug等等——看起来应该这样做
更新:
下面的Andrews回答为我提供了一个选项,我在思考这个问题时确实在考虑这个选项(输入),但我需要更多关于如何泛化linq查询的说明。有人能澄清这一点吗
干杯
Moo有几件事你可以试试 一种是定义一个接口,该接口具有三十个实体类共享的所有相关字段。然后,您可以让每个实体类实现这个接口(我们称它为
IMyEntity
)
public partial class EntityNumber1 : IMyEntity
{
}
对于每个实体(其中EntityNumber1
是其中一个实体类的名称)。当然,这仍然是30个不同的定义,但是您的CRUD操作类可以在IMyEntity
上操作,而不必每次都编写一个新的类
第二种方法是简单地将CRUD操作类泛化,如您所建议的:
public class ExampleAttributes<T> : IAttributeList
{
...
公共类示例属性:IAttributeList
{
...
允许您使用T作为操作的类型。当然,与第一个方法结合使用可能会更容易,因为您仍然需要检查属性的存在,并将实体强制转换为适当的类型或接口
编辑:
要检查实体上是否存在适当的属性,可能需要使用反射方法
typeof(T).GetProperties().OfType<PropertyInfo>().Count<PropertyInfo>(pi => pi.Name == "MyPropertyName" && pi.GetGetMethod().ReturnType == typeof(TypeIWant)) > 0
typeof(T).GetProperties().OfType().Count(pi=>pi.Name==“MyPropertyName”&&pi.getMethod().ReturnType==typeof(TypeIWant))>0
当然,将
TypeIWant
替换为您期望的属性类型,并将MyPropertyName
替换为您正在检查的属性名称。向指定类型的构造函数添加一个参数。然后您可以在内部使用它。一个类,可能在构造函数。对于泛化LINQ查询,最大的问题是您的DataContext具有基于类型的集合。有几种方法可以避免这种情况。您可以尝试使用反射来访问它,但这将需要相当多的黑客攻击,并且几乎会破坏LINQ to SQL提供的所有效率。
最简单的方法似乎是使用Dynamic LINQ。我没有亲自使用过它,但它似乎应该支持它。您可以在此线程中找到更多信息:
等等
也许其他人可以提供更多信息?这不一定是ans