C# 我的方法中的泛型和类型值显示错误
我正在尝试编写一个通用方法,下面的代码给出了错误 无法将类型“C# 我的方法中的泛型和类型值显示错误,c#,.net,entity-framework,generics,casting,C#,.net,Entity Framework,Generics,Casting,我正在尝试编写一个通用方法,下面的代码给出了错误 无法将类型“T2”转换为“T1” “T1”不包含“操作”的定义,也不包含扩展名 接受类型为“T1”的第一个参数的方法“Action”可以是 找到(是否缺少using指令或程序集引用?) 私有列表FillChildControlOnSave( 参考T1对象,参考列表_entityParent,参考列表_entityDetail) { foreach(T2 c整体细节) { if(c.Action==XERP.Entity.ActionMode.Ad
T2
”转换为“T1
”
“T1
”不包含“操作”的定义,也不包含扩展名
接受类型为“T1
”的第一个参数的方法“Action”可以是
找到(是否缺少using指令或程序集引用?)
私有列表FillChildControlOnSave(
参考T1对象,参考列表_entityParent,参考列表_entityDetail)
{
foreach(T2 c整体细节)
{
if(c.Action==XERP.Entity.ActionMode.Add)
增加(c)项;
var tmp=objEntity.PlnBOMDetails
.Where(p=>p.BOMDetailRecordID==c.BOMDetailRecordID&&
p、 BOMID==c.BOMID&&
p、 IsDeleted==false)
.FirstOrDefault();
如果(tmp!=null)
if(c.Action==Entity.ActionMode.Delete)
objController.Context.PlnBOMDetails.DeleteObject(tmp);
}
返回_entityDetail;
}
如果我将
T1
和T2
替换为PlnBOMMaster、PlnBOMDetail
,则上述语法工作正常。如何解决此泛型方法问题?如果要将T1
和T2
限制在某些类或接口上,则需要使用,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
注意:如果您的实体是由代码生成工具创建的,则必须使用来应用接口实现
当然,您可能无法使用objController.Context.PlnBOMDetails.Add(c)
。您必须将其替换为通用代码,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
//用于DbContext
objController.Context.Set().Add(c);
//对于ObjectContext
objController.Context.CreateObjectSet().AddObject(c);
当然,您也可以编写自己的方法来实现这一点。例如,
IDetail
/IMaster
接口可以有一个AddToContext(…)
方法,该方法接受上下文并将自身插入适当的集合中。然后在FillChildControlOnSave
中,您只需调用c.AddToContext(objconcontroller.Context)
如果要将T1
和T2
限制在某些类或接口上,则需要使用,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
注意:如果您的实体是由代码生成工具创建的,则必须使用来应用接口实现
当然,您可能无法使用objController.Context.PlnBOMDetails.Add(c)
。您必须将其替换为通用代码,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
//用于DbContext
objController.Context.Set().Add(c);
//对于ObjectContext
objController.Context.CreateObjectSet().AddObject(c);
当然,您也可以编写自己的方法来实现这一点。例如,
IDetail
/IMaster
接口可以有一个AddToContext(…)
方法,该方法接受上下文并将自身插入适当的集合中。然后在FillChildControlOnSave
中,您只需调用c.AddToContext(objconcontroller.Context)
如果要调用T1
和T2
实例上的成员,则必须告诉编译器有关这些类型的信息:
private T2 Bar<T1,T2>(T1 actionable) where T1 : IActionable, T2 : IActionResult
{
T2 result = actionable.Action();
return result;
}
如果要调用
T1
和T2
实例上的成员,则必须告诉编译器有关这些类型的一些信息:
private T2 Bar<T1,T2>(T1 actionable) where T1 : IActionable, T2 : IActionResult
{
T2 result = actionable.Action();
return result;
}
您正在使用此行循环浏览
T2
列表:
foreach (T2 c in _entityDetail)
if (c.Action == XERP.Entity.ActionMode.Add)
然后您将访问此行中c
的属性Detail
:
foreach (T2 c in _entityDetail)
if (c.Action == XERP.Entity.ActionMode.Add)
编译器如何知道类型T2
包含这样的属性
您需要将泛型约束为一种接口,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
接口IPlnBOMDetail{XERP.Entity.ActionMode操作{get;}
类PlnBOMDetail:IPlnBOMDetail{}
私有列表FillChildControlOnSave(参考T1对象、参考列表实体属性、参考列表实体细节)
其中T2:IPlnBOMDetail
其他代码也是如此
旁注:使用ref
参数是一种代码气味。我建议您阅读以下主题:。
TL;博士:说 您几乎不需要使用ref/out
您正在使用此行循环浏览
T2
列表:
foreach (T2 c in _entityDetail)
if (c.Action == XERP.Entity.ActionMode.Add)
然后您将访问此行中c
的属性Detail
:
foreach (T2 c in _entityDetail)
if (c.Action == XERP.Entity.ActionMode.Add)
编译器如何知道类型T2
包含这样的属性
您需要将泛型约束为一种接口,如下所示:
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity,
ref List<T1> _entityParent,
ref List<T2> _entityDetail)
where T1 : PinBOMMaster
where T2 : PinBOMDetail
{
...
}
// for DbContext
objController.Context.Set<T2>().Add(c);
// for ObjectContext
objController.Context.CreateObjectSet<T2>().AddObject(c);
interface IPlnBOMDetail { XERP.Entity.ActionMode Action {get;}}
class PlnBOMDetail : IPlnBOMDetail {}
private List<T2> FillChildControlOnSave<T1, T2>(ref T1 objEntity, ref List<T1> _entityParent, ref List<T2> _entityDetail)
where T2 : IPlnBOMDetail
接口IPlnBOMDetail{XERP.Entity.ActionMode操作{get;}
类PlnBOMDetail:IPlnBOMDetail{}
私有列表FillChildControlOnSave(参考T1对象、参考列表实体属性、参考列表实体细节)
其中T2:IPlnBOMDetail
其他代码也是如此
旁注:使用ref
参数是一种代码气味。我建议您阅读以下主题:。
TL;博士:说 您几乎不需要使用ref/out
但在这种情况下,我们不需要泛型,不是吗?:)即使在这种情况下,泛型仍然可以使用——例如,如果您希望返回类型与输入类型完全匹配。p.s.w.g感谢您的回复,我不能在where语句中使用PlnBOMMaster、PlnBOMDetail,因为这是一个常用方法,我需要在几次使用该方法,并使用我的几个entities@shamim同样的原则也适用,尽管您必须为实体创建接口。请参阅我的更新答案。p.s.w.g请您修复代码语法objController.Context.Set()。我在Context中没有任何Set方法,但在这种情况下,我们不需要泛型,不是吗?:)即使在这种情况下,泛型仍然可以使用——例如,如果您希望返回类型与输入类型完全匹配。p.s.w.g感谢您的回复,我无法详细使用PlnBOMMaster、PlnBOMDetail