Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我的方法中的泛型和类型值显示错误_C#_.net_Entity Framework_Generics_Casting - Fatal编程技术网

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