【问题标题】:How to assign different generic classes to same variable如何将不同的泛型类分配给同一个变量
【发布时间】:2018-03-03 18:20:15
【问题描述】:

我知道这个问题可能已经被问过很多次了,我的标题可能需要一些帮助,所以请在将我指向重复项后随时关闭这个问题......只是目前不确定如何正确搜索答案。

我遇到了一种情况,变量可能需要保存ISolrOperations<Class1> 的实例,或者它可能需要保存ISolrOperations<Class2> 的实例。问题是没有接口的基本版本,因此没有类我可以将变量定义为(对象除外,它显然不知道ISolrOperations<T> 的方法)能够容纳任一类。

所以我知道的唯一解决方案是 a) 执行 if/else 语句,在其中我在一个块中使用 ISolrOperations<Class1> 做我需要的一切,在另一个块中使用 ISolrOperations<Class2> 做我需要的一切,即使每个块都会基本上包含重复的代码。或者 b) 我可以使变量动态化,而只是丢失一些我的代码的编译时验证。

我正在考虑是否有某种方法可以创建一个具有非泛型基的泛型包装类。也许基地必须将其视为一个对象,但使用反射......但我喜欢把它搞砸;如果我必须经历那个麻烦,还不如使用动态关键字。

是否有更“合适”的设计模式来处理这种情况?或者我是在动态或编写大量代码之间做出选择,只是为了让自己感觉自己做得“正确”,而动态确实是最实用的解决方案?

编辑:其实我不确定动态是否能解决这个问题:/

编辑 2:不...其他代码将 lambdas 与需要强制转换的变量一起使用,我显然不知道在编译时要转换成什么,所以这不起作用。

【问题讨论】:

  • 你能不能创建基本的非泛型接口ISolrOperations,它也将由泛型接口实现......然后你可以将正常调用路由到泛型接口......或者创建装饰器的想法...... .
  • 我希望。它来自第 3 方 dll。我的意思是它是开源的,所以理论上我可以,但我绝对没有时间。
  • 另外一个想法虽然因为这是我用自己的代码做的第一件事(并且过去做过)。
  • 我明白了。 interface的方法是什么?
  • 我唯一感兴趣的是“查询”

标签: c# generics dynamic


【解决方案1】:

将类包装在实现所需接口的通用适配器类中。

如果您想搜索它的示例,这称为适配器模式。

通用适配器示例:

public class SomeGenericInterfaceAdapter<T> : INonGenericInterface
{
    private IGenericInterface<T> _someGenericInterface;
    public SomeGenericInterfaceAdapter(IGenericInterface<T> someGenericInterface)
    {
        _someGenericInterface = someGenericInterface;
    }

    public void SomeMethod()
    {
        _someGenericInterface.SomeMethod();
    }
}

public interface INonGenericInterface
{
    void SomeMethod();
}

public interface IGenericInterface<T>
{
    void SomeMethod();
}

【讨论】:

  • 所以我给出的例子听起来好像只有 2 个类,而在现实生活中还有更多。虽然适配器模式可以与 2 个非常不同的类一起工作……但在我的例子中,每个类已经基本相同了。我的意思是我知道它在技术上是不同的,因为每个泛型类都不同但仍然不同。呃……我猜不管我怎么做都会很乱。
  • 适配器类可以是通用的,但它实现的接口不一定是。这应该可以防止您必须为每个类都实现它。
  • 我已经添加了一个这样的例子。
【解决方案2】:

虽然我不确定,但这种方法可能会有所帮助。此方法使用适配器模式

public interface ISolrOperations<T> 
{
    SqlQuery<T> Execute();
}

public interface ISolrOperationsAdapter
{
    IEnumerable<Base> Execute();
}

//Idealy you have interfaces
public class Base { }
public class Class1 : Base { }
public class Class2 : Base { }  

public abstract class SolrOperationsAdapter : ISolrOperationsAdapter
{
    protected SolrOperationsAdapter()
    {
    }

    public IEnumerable<Base> Execute()
    {
        return ExecuteImpl();
    }

    protected abstract IEnumerable<Base> ExecuteImpl();
}


public class GenericSolrOperationsAdapter<T> : SolrOperationsAdapter
{
    private readonly ISolrOperations<T> _solrOperations;

    public static ISolrOperationsAdapter From(ISolrOperations<T> solrOperations)
    {
        return new GenericSolrOperationsAdapter<T>(solrOperations);
    }

    protected GenericSolrOperationsAdapter(ISolrOperations<T> solrOperations)
        : base()
    {
        _solrOperations = solrOperations;
    }

    //If you define interfaces you can return return IEnumerable<IInterface>
    protected override IEnumerable<Base> ExecuteImpl()
    {
        //here you can somehow convert result of query to your types(Class1, Class2 or some interface behind)
        return _solrOperations.Execute().ConvertTo<IEnumerable<Base>>();
    }
}

使用示例:

ISolrOperations<Class1> solrOperations = new SolrOperationsImplementation()
ISolrOperationsAdapter adapter = GenericSolrOperationsAdapter<Class1>.From(solrOperations);
IEnumerable<Base> result = adapter.Execute(); 

【讨论】:

  • 嗯......今晚可能不会尝试这个,但如果这有帮助,我会在这个周末告诉你。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2017-10-14
相关资源
最近更新 更多