2016-10-19 74 views
1

我有一个通用的接口,像这样:实现接口具体

public interface IHandler 
{ 
    T Process<T>(IProcess process) where T : new(); 
} 

有时我想具体实现接口,例如:

public class BoolHandler : IHandler 
{ 
    public bool Process<bool>(IProcess process) 
    { 
     // Do some work - set to true or false 
     return true; 
    } 
} 

这可能吗?

编辑: 目前我可以这样做:

// Injecct handler in Main and work with single handler 
ViewModel model = handler.Process<ViewModel>(process); 
DifferentModel model = handler.Process<DifferentModel >(process); 

随着上市我就必须这样做(这我想建议避免,它要求我创造一堆处理程序上飞):

IHandler<ViewModel> handler = new Handler<ViewModel>(); 
ViewModel viewModel = handler.Process(process); 

IHandler<DifferentModel> handler = new Handler<DifferentModel>(); // Create yet another handler - arrr 
DifferentModel viewModel = handler.Process(process); 
+5

移动参数'T'到'IHandler'接口,并从'Process'方法将其删除。方法的通用参数需要针对您的实现无法实现的所有适用类型统一工作。 – Lee

+0

实施取决于提供的类型吗?如果是这样,那么该方法不是“通用的” –

+0

“BoolHandler”和其他处理程序是否由同一个消费者使用(即想要多态消费它们)?如果不是,则可以有两个接口,一个非泛型接口和一个通用方法,另一个泛型接口使用非泛型方法。 –

回答

2

据我了解你的问题(从评论交换),一些处理程序可以处理任何类型的T(或许多类型T)和其他处理程序只能处理一种类型。此外,你想在多个消费者中消费这些处理程序。

这里是你可以做什么:这样

public interface IHandler //Can handle many types 
{ 
    T Process<T>(int process); 

    bool CanProcess<T>(); 
} 

public interface IHandler<T> //Can handle a single type 
{ 
    T Process(int process); 
} 

,然后创建从IHandler<T>一个适配器IHandler

这样创建两个接口

public class Adaptor<T> : IHandler 
{ 
    private readonly IHandler<T> handler; 

    public Adaptor(IHandler<T> handler) 
    { 
     this.handler = handler; 
    } 

    public T1 Process<T1>(int process) 
    { 
     if(!CanProcess<T1>()) 
      throw new Exception(
       "Contract violated. I cannot handle type " + typeof(T1).Name); 

     return (T1)(object)handler.Process(process); 
    } 

    public bool CanProcess<T1>() 
    { 
     return typeof (T1) == typeof (T); 
    } 
}  

现在,您的复合材料可以做这样的事情:

public class CompositeHandler : IHandler 
{ 
    private readonly IHandler[] handlers; 

    public CompositeHandler(params IHandler[] handlers) 
    { 
     this.handlers = handlers; 
    } 

    public T Process<T>(int process) 
    { 
     var handler = handlers.FirstOrDefault(h => h.CanProcess<T>()); 

     if(handler == null) 
      throw new Exception(
       "Contract violated. I cannot handle type " + typeof(T).Name); 

     return handler.Process<T>(process); 
    } 

    public bool CanProcess<T>() 
    { 
     return handlers.Any(h => h.CanProcess<T>()); 
    } 
} 

现在,您可以将任何IHandler<T>实现改编为IHandler并通常将其用作IHandler。例如,您可以将其用作组合的一部分。

下面是一个例子组合物:

var service = new CompositeHandler(
    new TypeThatImplementsTheNonGenericInterface(), 
    new Type2ThatImplementsTheNonGenericInterface(), 
    new Adaptor<SomeType>(
     new TypeThatImplementsTheGenericInterface<SomeType>())); 
+0

这个帮了很多!=谢谢 – ShaneKm

+0

不客气 –

0

你可以尝试这种模式

public interface IHandler<T> where T : new() 
    { 
     T Process(IProcess process); 
    } 

    public interface IProcess 
    { 
    } 

    public class BoolHandler : IHandler<bool> 
    { 
     public bool Process(IProcess process) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
+0

只是注意到这是李在他的评论中说 - 无论如何它写出来为你 – Banners

+0

这种方法的问题是,我必须为每个类型创建单独的处理程序。用我上面的我可以做var result = _handler.Process (); – ShaneKm

+0

@ShaneKm - “Process”的实现将如何创建您提供的任何类型的实例? (例如,为'bool'和'MyResult'工作)。这在一般情况下是不可能的(忽略反射),如果你打算这么做,你可以完全从“Process”中移出逻辑。 – Lee

3

不,它是不是可能。您的界面指出,任何实施类必须具有方法,其中该方法可以与任何类型的 [满足通用约束]一起使用。如果你的类只适用于例如布尔值,那么你没有履行接口指定的合同,所以类型不能实现那个接口。

0

我知道有人会说这不是一个好的做法,但它是一种替代方案。您可以在界面object取代通用T,并做一些强制转换:

public interface IHandler 
{ 
    object Process(IProcess process); 
} 

public class BoolHandler : IHandler 
{ 
    object Process(IProcess process){ return true;} 
} 

这将是 implementig与通用声明的接口,但这样一来,你答应网友认为BoolHandler总会返回一个布尔值。