简体   繁体   English

C#通用方法T类T重写

[英]C# Generic Method T Class T Override

In C# I have a generic class that looks like this: 在C#中,我有一个通用类,如下所示:

public class DataManager<T> : IDisposable where T : class

That is used like this: 这样使用:

    public T GetById(String id)
    {
        return this.Context.Set<T>().Find(id);
    }

This works great. 这很好。

However if I have 2 types in a manager, in this case, Ticket and TicketResponse, I would like to be able to override the type without having to add the type into every method call. 但是,如果我在管理器中有2种类型(在这种情况下为Ticket和TicketResponse),我希望能够重写类型,而不必将类型添加到每个方法调用中。 Something like this: 像这样:

    public T GetById<T>(String id) where T : class
    {
        return this.Context.Set<T>().Find(id);
    }

Where I can call it interchangeably like so: 我可以这样互换地称呼它:

    var ticket = GetById(myId);
    var ticketResponse = GetById<TicketResponse>(myId); // this would override

The idea is to not have to create a separate manager for a sub-object, but also to not have to get the entire ticket to have to iterate through the responses, but just be able to get it directly. 这样做的想法是不必为子对象创建单独的管理器,也不必不必花费整个票证就可以遍历响应,而只能直接获得它。

Is this possible? 这可能吗?

Since the Context.Set allows you to specify any T you want, you could add an interface for the DataManager class, add a base class which exposes a method on the underlying context and then implement the interface explicitly on your manager class: 由于Context.Set允许您指定所需的任何T ,因此您可以为DataManager类添加一个接口,添加一个在基础上下文中公开方法的基类,然后在您的管理器类上显式实现该接口:

public interface IDataManager<T> : IDisposable where T : class
{
    T GetById(string id);
}

public class DataManagerBase : IDisposable
{
    protected Find<T>(string id) where T : class
    {
        return this.Context.Set<T>().Find(id);
    }
}

public class TicketManager : DataManagerBase, IDataManager<TicketResponse>, IDataManager<Ticket>
{
    TicketResponse IDataManager<TicketResponse>.GetById(string id)
    {
        return this.Find<TicketResponse>(id);
    }

    Ticket IDataManager<Ticket>.GetById(string id)
    {
        return this.Find<TicketResponse>(id);
    }
}

You could try something like this: 您可以尝试这样的事情:

public T GetById( String id )
{
    return GetById<T>( id );
}

public U GetById<U>( String id ) where U : T
{
    return this.Context.Set<U>().Find( id );
}

So you have your original method but also an additional generic method which can take another parameter type that derives from T . 因此,您既有原始方法,又有其他通用方法,可以采用从T派生的另一种参数类型。

If I understood you correctly, Ticket is a special case: Ticket 's DataManager should also provide methods for TicketResponse . 如果我对您的理解正确,那么Ticket是一种特殊情况: Ticket的DataManager 应该提供TicketResponse方法。 Is that correct? 那是对的吗?

In that case, you can just subclass DataManager<T> and add the required functionality: 在这种情况下,您可以仅DataManager<T>并添加所需的功能:

class TicketManager : DataManager<Ticket>
{
    public TicketResponse GetResponseById(String id)
    {
        return this.Context.Set<TicketResponse>().Find(id);
    }
}

which can be used as follows: 可以如下使用:

var ticket = myTicketManager.GetById(myId);
var ticketResponse = myTicketManager.GetResponseById(myId);

(If you are worried about the duplication of the GetById code, just extract it into a static protected GetByIdInternal<TData> method.) (如果您担心GetById代码的重复,只需将其提取到受静态保护的GetByIdInternal<TData>方法中即可。)

You could use a wrapper that encapsulates two DataManagers: 您可以使用封装两个 DataManager的包装器:

class DataAndResponseManager<TData, TResponse>
{
    private dataManager = new DataManager<TData>();
    private responseManager = new DataManager<TResponse>();

    public TData GetById(String id) { dataManager.GetById(id); }
    public TResponse GetResponseById(String id) { responseManager.GetById(id); }
}

Advantage: Reuse of all existing DataManager code. 优点:重用所有现有的DataManager代码。

Disadvantage: Proxy methods required. 缺点:需要代理方法。

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

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