2011-03-29 119 views
2

我正在爲Silverlight創建可重用的庫。該庫包含一個內部的泛型類型,我需要創建一個新的泛型類型的實例,但我在某一點上我沒有泛型類型參數可用,只有代表泛型參數的System.Type對象。我試圖使用反射來創建一個實例,但是這種方法失敗了,因爲這個類是內部的,並且Silverlight有效地以部分信任運行。部分信任:如何在沒有泛型類型參數的情況下實例化泛型類型

這裏是我試過到目前爲止:

private INonGenericInterface CreateInstance(Type type) 
{ 
    // Activator.CreateInstance fails 
    var instance = Activator.CreateInstance(
      typeof(InternalGenericType<>).MakeGenericType(type)); 

    // Invoking the default constructor of that type fails. 
    var producer = typeof(InternalGenericType<>) 
     .MakeGenericType(type) 
     .GetConstructor(new Type[0]) 
     .Invoke(null); 

    return (INonGenericInterface)producer; 
} 

這是我的內部類。沒有什麼幻想:

internal class InternalGenericType<T> : INonGenericInterface 
    where T : class 
{ 
    public InternalGenericType() 
    { 
    } 
} 

我甚至嘗試濫用Nullable<T>結構的一個工廠建立一個工廠,可以生產我的內部類。然而,默認Nullable<T>地轉化爲空引用:

internal static class InternalGenericTypeFactory 
{ 
    public static INonGenericInterface Create(Type serviceType) 
    { 
     var nullType = typeof(Nullable<>).MakeGenericType(
     typeof(Factory<>).MakeGenericType(serviceType)); 

     // Activator succesfully creates the instance, but .NET 
     // automatically converts default Nullable<T>s to null. 
     object nullInstance = Activator.CreateInstance(nullType); 

     var getValueMethod = 
     nullType.GetMethod("GetValueOrDefault", new Type[0]); 

     // Invoke fails, because nullInstance is a null ref. 
     var factory = getValueMethod.Invoke(nullInstance, null); 

     return ((IFactory)factory).CreateInstance(); 
    } 

    internal interface IFactory 
    { 
     INonGenericInterface CreateInstance(); 
    } 

    internal struct Factory<T> : IFactory where T : class 
    { 
     public INonGenericInterface CreateInstance() 
     { 
      return new InternalGenericType<T>(); 
     } 
    } 
} 

正如你可以想像,我不想讓這種類型的公衆,因爲它會污染我的API。我目前沒有想法。我有什麼選擇?我能做些什麼來創建這種內部類型?

回答

4

第三種選擇是支持某種工廠模式,它將包含一個instanciate內部類型的方法。並且您可以公開工廠或使工廠類型公開。

public class TypeFactory 
{ 
    public static object Create<T>() 
    { 
     return new MyInternalType<T>(); 
    } 
} 

你可以離開類內部,你可以通過反射調用TypeFactory的方法。

public object CreateType(System.Type type) 
{ 
    Type typeFactory = typeof(TypeFactory); 
    MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type); 
    return m.Invoke(null, null); 
} 

我認爲你的TypeFactory應該是公共的,它不能是內部的。

+0

我不知道我跟着你。你能給個例子嗎? – Steven 2011-03-29 18:51:46

+0

@Akash:感謝這個例子,但是這不幸的是我不能做這個伎倆,因爲我沒有一個通用的'T',只是一個代表'T'的'System.Type'。 – Steven 2011-03-29 19:38:33

+0

T從哪裏來?你不能提供一個工廠代表或其他東西嗎? – 2011-03-29 19:56:25

3

你有兩個選擇:

  1. 使用反射來做到這一點使該類型的公共
  2. 避免使用泛型代替。

如果保護措施可以避免只是因爲你不喜歡它們,根本就不需要它們。

+0

感謝您的回覆。我並不想避免Silverlight安全機制,不用擔心:-)。我擔心這些是我的選擇。 – Steven 2011-03-29 18:36:34

+0

道歉,如果它聽起來像我暗示你是,但是,這些是你的選擇,由於Silverlight的安全系統。我假設在完全信任的Silverlight中創建瀏覽器外的應用程序不是一種選擇嗎? – 2011-03-29 18:38:29

+0

完全信任運行不是一種選擇。它是一個可重用的庫,限制我的用戶完全信任地運行它,這只是一個太大的限制。 – Steven 2011-03-29 18:41:57