类型推断问题:非泛型方法的通用方法参数

时间:2011-02-13 00:04:09

标签: c# generics type-inference

首先,我知道标题不是那么好但事情是我甚至不知道如何解释我的问题;我将在下面展示一下我正在尝试做的事情:

编辑:我本来应该给出一个更好的例子;让我们再试一次:

// MyAppComponentModel.dll
namespace MyAppComponentModel {
  using System.Collections;

  interface IResource { }
  interface IStringResource : IResource { }
  interface IIconResource : IResource { }
  interface IDialogResource : IResource { }
  interface IResourceProvider {
    void GetResource<T>(out T result, IDictionary criteria = null) where T : IResource;
  }
}

// ThirdPartyLib.dll
namespace ResourceProviderLibA {
  using System.Collections;
  using System.ComponentModel.Composition;
  using MyAppComponentModel.

  public sealed class StringResource : IStringResource { ... }
  public sealed class IconResource : IIconResource { ... }

  [Export(typeof(IResourceProvider))]
  public sealed class StringAndIconResourceProvider : IResourceProvider {
    void IResourceProvider.Get<T>(out T result, IDictionary criteria) {
      if (typeof(T) == typeof(IDialogResource))
        throw new NotSupportedException();

      this.InternalGet(out result, criteria);
    }

    void InternalGet(out IStringResource result, IDictionary criteria) {
      result = new StringResource();
      ...
    }

    void InternalGet(out IIconResource result, IDictionary criteria) {
      result = new IconResource();
      ...
    }
  }
}

// MyMefTestApp.exe
namespace MyMefTestApp {
  using System.Collections.Generic;
  using System.ComponentModel.Composition.Hosting;
  using MyAppComponentModel.

  static class Program {
    [ImportMany(typeof(IResourceProvider))]
    private IEnumerable<IResourceProvider> mProviders;

    static void Main(String[] args) {
      foreach (var provider in this.mProviders) {
        ...
      }
    }
  }
}

我知道这在某种程度上是可能的,我坚信我曾经做过类似的事情。任何人吗?

我已经知道这可以通过Reflection完成,所以请跳过这些解决方案 - 谢谢。

2 个答案:

答案 0 :(得分:2)

这是不可能的,因为T可以是任何内容(编译器错误实际上是cannot convert from 'out T' to 'out string'),而不仅仅是stringint

只需将privateFoo重载公开为公开Foo并完成,没有其他办法,因为您无法将通用限制为stringint (两者都是密封的,泛型类型约束需要接口或非密封类)。

编辑(已更改的问题)

如果您的Resource实现只有无参数构造函数,我会使用它(精简示例):

interface IHostProvider
{
  void Get<T> (out T result) where T : IHost,  new();
}

public interface IHost
{
}

public class Something : IHost
{
}

public class Provider : IHostProvider
{
  public void Get<T> (out T result) where T: IHost, new()
    {
      result = new T();
    }
}

如果他们需要参数但是... phew,不知道这个深夜。起初我考虑过静态工厂方法,但由于您不能在接口中使用静态方法,也不能将其标记为抽象,这也不起作用。

答案 1 :(得分:0)

你的样本在我看来是不可能的。编译器可以从已知的实际参数类型推断方法的类型参数。例如:

void DoSomething<T>(T item)
{
    ...
}

IFoo foo =  default(IFoo);
DoSomething(foo); // void DoSomething<IFoo>(IFoo item);

但是编译器不能做相反的事情。编译器无法猜测T的实际类型,这就是为什么它无法选择适用的方法过载。

void DoSomething(IFoo foo)
{
    ...
}

T item = default(T);
DoSomething(item); // won't compile unless it is known that T is IFoo (where T : IFoo)