2011-02-13 152 views
1

首先,我知道標題不是很好,但事實是我甚至不知道如何解釋我的問題;我將在下面展示一個我想要做的事例:類型推斷問題:非泛型方法的泛型方法參數

編輯:我應該給出一個更好的例子來開始;讓我們再試一次:

// 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) { 
     ... 
     } 
    } 
    } 
} 

我知道這是在某種程度上可能的,我堅信我做了這樣的事情曾經只是不記得如何。任何人?

我已經知道這可以通過反射完成,所以請跳過這些解決方案 - 謝謝。

回答

2

這是不可能的,因爲T可以是任何東西(編譯錯誤實際上是cannot convert from 'out T' to 'out string'),而不僅僅是一個stringint

剛剛露出privateFoo重載公共Foo並用它做,還有,你不能限制一個通用的stringint(兩者都是密封的,泛型類型約束需要一個接口或非沒有其他辦法密封類)。

編輯(改變問題)

如果你的資源實現只有參數構造函數,我會用這個(濃縮爲例):如果他們需要參數但是......唷

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(); 
    } 
} 

,不知道這在深夜。起初我有一個靜態工廠方法,但是因爲你不能在接口中需要一個靜態方法,也不能將其標記爲抽象,這也不起作用。

+0

我已將示例代碼更新爲更實用的示例;請看看它,看看它是否以任何方式改變你的答案。我真的需要一些幫助,或者至少有一個「良好的編程」方式來解決這個問題。 – gplusplus 2011-02-13 00:39:58

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)