Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.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#中,我可以播放MyService<;儿童>;为我服务<;基础>;?_C#_Casting_Asp.net Core_Polymorphism_Generic Programming - Fatal编程技术网

在C#中,我可以播放MyService<;儿童>;为我服务<;基础>;?

在C#中,我可以播放MyService<;儿童>;为我服务<;基础>;?,c#,casting,asp.net-core,polymorphism,generic-programming,C#,Casting,Asp.net Core,Polymorphism,Generic Programming,背景:我们有一个基于ASP.NET Core的web应用程序,使用在DI和通用存储库模式之上开发的EF Core。因此,大多数事情都是使用接口完成的。现在,我们已经到达主表维护模块。我们不希望为所有10-20个主表复制相同的服务(由存储库支持)类 因此,我们创建了一个\u ModelMasterBase类,并从中派生出所有主表类。所有主表的积垢都是相同的。接下来,我们实现了MasterRepository,MasterService及其接口。现在一切都必须使用,其中T是在页面上选择用于执行CRU

背景:我们有一个基于ASP.NET Core的web应用程序,使用在DI和通用存储库模式之上开发的EF Core。因此,大多数事情都是使用接口完成的。现在,我们已经到达主表维护模块。我们不希望为所有10-20个主表复制相同的服务(由存储库支持)类

因此,我们创建了一个
\u ModelMasterBase
类,并从中派生出所有主表类。所有主表的积垢都是相同的。接下来,我们实现了
MasterRepository
MasterService
及其接口。现在一切都必须使用
,其中
T
是在页面上选择用于执行CRUD的主表的类型

最初,我希望
IMasterService
的实例可以转换为
IMasterService
-同样地,
T
可以是从
\u ModelMasterBase
派生的任何子类,但这似乎是不可能的!我试过运营商,演员,几乎所有我能用谷歌搜索的东西!此外,由于存储库模式,所有内容都必须是强类型的

现在,我们已经使用技巧将子obj转换为基类obj,如下所示-

DerivedClass B=新的DerivedClass();
BaseClass bc=JsonConvert.DeserializeObject(JsonConvert.SerializeObject(B));
我知道这有点肮脏,但有时在设计和复杂性之间保持平衡很方便。我们谨慎地使用它。如果我想将
MyService
转换为
MyService

或者你可以忘记这一切,指导我为所有主表提供单点CRUD服务——将同一个东西复制10-20次似乎是不合理的。对不起,我无法深入解释,因为这会使文章显得冗长

这是一个v.basic,最后你会看到我们正在努力实现的目标。希望能有帮助


解决方案:

根据mkArtak的建议,我可以使用 “”概念()。这是我的现在所有主表都有一个控制器和服务层

继承问题? 这种事情闻起来你应该更喜欢组合而不是继承。正如您所说的,您能够将专用类序列化/反序列化为基类,从定义上讲,这不是更像一个数据传输对象吗?我不会将逻辑放入这些服务中,而是引入另一个使用基类逻辑而不进行继承的服务(例如,将实例传递到构造函数中)——这可能首先解决问题

不是解决办法 对于您的特定问题:如果没有太多限制(例如,您只能在参数中使用类型参数,而不能在返回类型中使用类型参数),并且您拥有相关的接口,则可以使用。但是编译器只允许我以另一种方式分配服务,这是有意义的。也许你可以用协变的方式来解决这个问题

使用系统;
公共课程
{
内部接口IMasterService{
无效剂量测定(T表);
}
内部类基类{}
内部类DerivedClass:基类{}
内部类SpezializedService:IMasterService{
公共void DoSomething(基类表){}
}
公共静态void Main()
{
//编译器对另一种方式不满意
IMasterService baseService=新的SpezializedService();
}
}

希望这能有所帮助。

简短回答:在IMasterService定义中,前缀T带有'out'关键字

public interface IMasterService<out T>
{
    // your existing methods' definitions here
}
公共接口IMasterService
{
//您现有方法的定义在这里
}

它被称为协方差,如中所述。

通常的例子是
List
。如果您可以将其强制转换为
列表
,那么任何人都可以向列表中添加任何内容,这肯定会混淆任何希望
列表
只能包含
字符串
的代码。同意,但在我的情况下,我们想知道是否有办法以某种方式实现它-知道确切的装箱和拆箱场景。就像我们可以做的一样-List result=data.Cast().ToList();-其中数据可以是一个列表,T来自_ModelBaseMaster。谢谢。您能否抽出一些时间来看看我的简短代码示例,并帮助我了解您的解决方案将如何解决它。@HemantTank问题是,您只能将协变类型用作返回类型,而不能用于像代码示例这样的输入参数suggests@HemantTank,修复方法是添加“out”对于IMasterService定义中的类型参数。它将增强IMasterService和IMasterService实现之间的兼容性,因此您可以编写如下内容:IMasterService baseMasterService=childMasterService;//Whare childMasterService是IMasterService类型。在VB.Net中,您应该使用以下接口声明:接口IMasterService End接口您是生命的救世主!我费了很大的劲,这样一个小小的补救似乎是不可能的。我的下一步是解决我的CRUD例程,比如-voidadd(tmobj);错误:无效差异:类型参数“T”在“IMasterService.Add(T)”上必须相反有效T’是convariablethes@hemantank,看起来您必须将Add方法设置为通用的,如下所示:void Add(V)where V:BaseClass;谢谢你详细的解释,我想已经结束了。请您抽出一些时间来看看我的简短代码示例,并帮助我了解您的解决方案将如何修复它。
public interface IMasterService<out T>
{
    // your existing methods' definitions here
}