2012-10-08 68 views
4

我有如下功能。如何使用泛型將我的類轉換爲動態類型<T>

private IList<ContactList> getEmptyRow() 
{ 
    var _ContactList = new List<ContactList>(); 
    _ContactList.Add(new ContactList() 
    { 
     Email = string.Empty, 
     Name = string.Empty 
    }); 

    return _ContactList; 
} 

我想改變我的課ContactList

private IList<T> getEmptyRow() { ..... T.Add(new T().... 

這可能嗎?如何 ?
每個建議將不勝感激。

回答

6

也許這樣的事情?

public interface IPerson 
{ 
    string Email {get;set;} 
    string Name {get;set;} 
} 

public class SomeClass 
{ 
    private IList<T> getEmptyRow<T>() where T : IPerson, new() 
    { 
     var t = new List<T>(); 
     t.Add(new T() 
     { 
      Email = string.Empty, 
      Name = string.Empty 
     }); 

     return t; 
    } 
} 

你需要一個接口或基類,您可以設置的公共屬性EmailName和你所需要的new()約束,所以你可以使用默認的構造函數。

+0

這也假定IPerson的所有實現都存在無參數構造函數。 –

+0

在'where T:IPerson,new()'中給動態對象起作用而不是直接使用IPerson是不可能的? –

4

有點晚了,因爲你已經接受了答案,但作爲替代,特別是如果new()是不是一種選擇,你可以設置與預先定義的構造函數/初始化語法提供商應該給你一定的靈活性:

public static class EmptyRowProvider 
{ 
    private static Dictionary<Type, object> TypeCreators = new Dictionary<Type, object>(); 

    public static void RegisterType<T>(Func<T> emptyTypeCreator) 
    { 
     TypeCreators.Add(typeof(T), emptyTypeCreator); 
    } 

    public static IList<T> GetEmptyRow<T>() 
    { 
     object typeCreatorUntyped; 
     if (!TypeCreators.TryGetValue(typeof(T), out typeCreatorUntyped)) 
      throw new Exception("Type " + typeof(T).FullName + " not registered!"); 

     Func<T> typeCreator = (Func<T>)typeCreatorUntyped; 

     IList<T> emptyRow = new List<T>(); 
     emptyRow.Add(typeCreator()); 
     return emptyRow; 
    } 
} 

在您的應用程序初始化過程中,您可能會註冊類型及其工廠方法。後來,你只要把由型呼叫這將運行方法:如果你有一個類型,你沒有爲參數的構造函數,或者如果以後你決定改變

EmptyRowProvider.RegisterType(() => new ContactList() { Email = String.Empty, Name = String.Empty }); 


var emptyRow = EmptyRowProvider.GetEmptyRow<ContactList>(); 

Console.WriteLine(emptyRow.Count); //1 
Console.WriteLine(emptyRow[0].Email == String.Empty); //true 
Console.WriteLine(emptyRow[0].Name == String.Empty); //true 

說它的初始化方式。後來說你有ContactList使用不同的構造函數:

public ContactList(string email, string name, bool isPrivate) 
{ 
    //initialize data here 
} 

那麼你的新代碼的使用可能看起來像:

EmptyRowProvider.RegisterType(() => new ContactList(String.Empty, String.Empty, true)); 


var emptyRow = EmptyRowProvider.GetEmptyRow<ContactList>(); 

Console.WriteLine(emptyRow.Count); //1 
Console.WriteLine(emptyRow[0].Email == String.Empty); //true 
Console.WriteLine(emptyRow[0].Name == String.Empty); //true 
Console.WriteLine(emptyRow[0].IsPrivate == true); //true 

或者說你推ContactList創建一個特定的工廠方法:

EmptyRowProvider.RegisterType(() => ContactListFactory.Create(String.Empty, String.Empty)); 

最後,您可以註冊具有不同初始化的多種不同類型,但實現相同的用法:

EmptyRowProvider.RegisterType(() => new ContactList(String.Empty, String.Empty, true)); 
EmptyRowProvider.RegisterType(() => new Person("John", "Doe")); 
EmptyRowProvider.RegisterType(() => UserProvider.SetupAnonymousUser("myusername", "mypassword", LoginType.Anonymous)); 

ContactList emptyContactList = EmptyRowProvider.GetEmptyRow<ContactList>(); 
Person emptyPerson = EmptyRowProvider.GetEmptyRow<Person>(); 
User emptyUser = EmptyRowProvider.GetEmptyRow<User>(); 
+0

非常好的答案。我很欣賞你的努力。 @Chris Sinclair –

+0

我喜歡在代碼中註冊多種不同類型的方式。 –

+0

@Frank:不客氣!快樂的編碼! –