简体   繁体   English

C# 接口:使用通用接口处理实例类

[英]C# Interface: Handling instance classes using generic interface

We are trying to build a web api request to handle different type of business actions in a common endpoint.我们正在尝试构建一个 web api 请求,以在一个公共端点中处理不同类型的业务操作。 We have got a parent model class which holds common fields, and each business type has its own class inheriting from base model class. We have got a parent model class which holds common fields, and each business type has its own class inheriting from base model class. Controller input type will be the base class and client must specify the type being sent in the request (designated enum value for each type, not the fully qualified type name). Controller 输入类型将是基本 class 并且客户端必须指定在请求中发送的类型(为每种类型指定的枚举值,而不是完全限定的类型名称)。 We have created a custom de-serialiser to convert the received object to actual type based on the specified type.我们创建了一个自定义的反序列化器,根据指定的类型将收到的 object 转换为实际类型。

Like model classes, we have got base interface inherited by each business type.像 model 类一样,我们有每个业务类型继承的基本接口。 Since the actions are same across different business types and only the input and output types of each action varies, we defined a generic base interface holding all the actions.由于不同业务类型的操作相同,并且每个操作的输入和 output 类型不同,因此我们定义了一个通用的基本接口来保存所有操作。 Each business specific class inherits interface by specifying relevant model type during inheritance.每个业务特定的 class 通过在 inheritance 期间指定相关的 model 类型来继承接口。

Problem trying to solve:试图解决的问题:

I know the model type through custom de-serialiser.我通过自定义解串器知道 model 类型。 Based on this type I must get the instance of class inheriting the interface for the identified type and call the method of that service.基于这种类型,我必须获取继承识别类型接口的 class 实例并调用该服务的方法。 How to achieve this?如何做到这一点?

Written below method but getting runtime exception for invalid casting写在方法下面,但因无效转换而获得运行时异常

private static ITransactionService<Transaction> GetServiceInstance(Transaction transaction)
{
    return transaction switch
    {
        Commitment => (ITransactionService<Transaction>)new CommitmentService(),
        Drawdown => (ITransactionService<Transaction>)new DrawdownService(),
        _ => null
    };
}

Below is the complete code structure for reference:以下是完整的代码结构供参考:

public class Transaction
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
}
public class Commitment : Transaction
{
    public string Investor { get; set; }
    public int Quantity { get; set; }
}
public class Drawdown : Transaction
{
    public decimal Amount { get; set; }
}
public interface ITransactionService<T> where T : Transaction
{
    T Create(T transaction);
    T Update(T transaction);
    T Apporve(T transaction);
}
public class CommitmentService : ITransactionService<Commitment>
{
    public Commitment Apporve(Commitment transaction)
    {
        throw new NotImplementedException();
    }

    public Commitment Create(Commitment transaction)
    {
        throw new NotImplementedException();
    }

    public Commitment Update(Commitment transaction)
    {
        throw new NotImplementedException();
    }
}
public class DrawdownService : ITransactionService<Drawdown>
{
    public Drawdown Apporve(Drawdown transaction)
    {
        throw new NotImplementedException();
    }

    public Drawdown Create(Drawdown transaction)
    {
        throw new NotImplementedException();
    }

    public Drawdown Update(Drawdown transaction)
    {
        throw new NotImplementedException();
    }
}

The exception I am getting:我得到的例外:

在此处输入图像描述

Basically we are trying to reduce number of classes and endpoints need to be created for each type.基本上,我们正在尝试减少需要为每种类型创建的类和端点的数量。

You have a variance problem, ITransactionService<Commitment> can't be cast to ITransactionService<Transaction> .你有一个方差问题, ITransactionService<Commitment>不能转换为ITransactionService<Transaction> Some variance problems can be solved by adding in or out keywords .一些方差问题可以通过添加inout 关键字来解决。

But in general all variance problems can be solved with either more generics.但总的来说,所有方差问题都可以通过更多 generics 来解决。 Forcing the caller to either know the actual type, or invoke the methods via reflection;强制调用者要么知道实际类型,要么通过反射调用方法;

private static ITransactionService<T> GetServiceInstance<T>(T transaction)

Or more types with less generics.或更多类型,更少 generics。 Adding methods that allow the caller to access features without needing to know the actual type;添加允许调用者在不需要知道实际类型的情况下访问功能的方法;

public interface ITransactionService
{
    Transaction Create(Transaction transaction);
    Transaction Update(Transaction transaction);
    Transaction Apporve(Transaction transaction);
}
public interface ITransactionService<T> : ITransactionService where T : Transaction
{
    T Create(T transaction);
    T Update(T transaction);
    T Apporve(T transaction);
}
public abstract class BaseService<T> : ITransactionService<T> where T : Transaction
{
    Transaction ITransactionService.Apporve(Transaction transaction)
        => Apporve((T)transaction);
    public abstract T Apporve(T transaction);

    Transaction ITransactionService.Create(Transaction transaction)
        => Create((T)transaction);
    public abstract T Create(T transaction);

    Transaction ITransactionService.Update(Transaction transaction)
        => Update((T)transaction);
    public abstract T Update(T transaction);
}

Now every ITransactionService<T> has a known base type, ITransactionService that you can cast.现在每个ITransactionService<T>都有一个已知的基类型ITransactionService ,您可以转换它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM