2010-02-25 76 views
2

我有兩個類通用C#方法

public class JobDataProvider 
{ 
    public List<Job> Get(int id){ 
     List<Job> jobs = new List<Job>(); 
     foreach(up_GetJobResult result in myDataContext.up_GetJob(id)) 
     { 
      jobs.add(new Job(Id = result.Id, name = result.Name)); 
     } 
    return jobs; 
    } 
}//end class Job 

public class PersondataProvider{ 
    public List<Person> Get(int id){ 
     List<Person> persons = new List<Persons>(); 
     foreach(up_GetPersonsResult result in MyDataContext.up_GetPerson(id)){ 
      persons.add(new Person(Id = result.Id, Name = result.Name, Surname =  result.Surname)); 
      } 
     return persons; 
    } 
}end class Person 

我想創建一個通用的方法,這樣的事情

public List<T> Get<T>(int id) 
{ 
    .. get data and return the list 
} 
+1

Job和Person類之間是否有任何關係?他們有共同的基礎班嗎? – 2010-02-25 22:17:53

+0

除非工作與人之間存在明確的關係,並且您更多地重構代碼以提取抽象並且具有構建人員和工作(例如因子)的常見方式,否則我認爲迄今爲止提交的任何答案都不起作用。除了你從數據上下文調用不同的方法,你正在使用不同的參數 – 2010-02-25 23:05:14

回答

0

這裏有一些可能性。

IEnumerable<T> Get<T>(int id) { } // returns an IEnumerable containing the data 
            // can use yield return inside to eable deferred execution 

IList<T> Get<T>(int id) { }  // returns a list 

T Get<T>(int id) { }    // returns a single object 
1

除非您想要傳遞T的數據與具有存儲過程的DataContext之間存在共同的接口或鏈接,否則這可能很難實現。

但是,您可能能夠利用.NET 4.0中的DynamicObject功能來執行此操作。如果你的MyDataContext對象是一個DynamicObject,你可以使用約定,你的數據檢索方法總是up_GetFoo,其中Foo也是你的返回類型與TryGetMember一起做到這一點。

2

你並沒有完全問一個問題,但我會看看我是否能猜出你在問什麼。你需要一個通用的方法,你可以指定你想要返回的類型和一個ID,並讓泛型方法找出從哪裏獲取數據。

您可以創建一個字典,其中鍵爲類型(T),值爲要返回的列表,或者可能是返回所需列表的接口實例(如果列表是動態的,而您不想將它存儲在多個地方)。

這是您可能嘗試的一個接口(您顯然希望添加更多的錯誤處理)。當然這個例子假設你不僅有一個明確的接口(IDataProvider),而且還有一個隱式接口(IDataProvider.Get必須返回一個正確類型的通用List)。

public interface IDataProvider 
{ 
    IEnumerable Get(int id); 
} 

public class JobDataProvider 
    : IDataProvider 
{ 

    public List<Job> Get(int id) 
    { 
    var jobs = new List<Job>(); 
    // load jobs 
    return jobs; 
    } 

    IEnumerable IDataProvider.Get(int id) 
    { 
    return Get(id); 
    } 
} 

public class PersonDataProvider 
    : IDataProvider 
{ 

    public List<Person> Get(int id) 
    { 
    var people = new List<Person>(); 
    // load people 
    return people; 
    } 

    IEnumerable IDataProvider.Get(int id) 
    { 
    return Get(id); 
    } 
} 

public class ItemDataProvider 
{ 
    private Dictionary<Type, IDataProvider> mProviders = new Dictionary<Type, IDataProvider>(); 
    public void RegisterProvider(Type type, IDataProvider provider) 
    { 
    mProviders.Add(type, provider); 
    } 

    public List<T> Get<T>(int id) 
    { 
    var data = mProviders[typeof(T)].Get(id); 
    return (List<T>)data; 
    } 
} 

public class Job 
{ 
} 

public class Person 
{ 
} 
+0

對不同的構造函數(罰款,如果只有默認的構造函數)對不起,我不完全理解你的代碼....當我從數據庫中獲得列表up_GetPersonResult(當/如何)我將項目添加到列表中? – GigaPr 2010-02-25 22:36:57

+0

我更新了示例代碼以正確反映您的代碼段。 – Brian 2010-02-26 01:46:34

0

你需要一個接口

public interface IProvider<TKey, TValue> 
{ 
    IList<TValue> Get(TKey id); 
} 

接下來,你的公共類需要實現這個接口:

public class JobDataProvider : IProvider<Job, int> 
{ 
    public IList<Job> Get(int id) 
    { 
    } 
} 

現在,你有你要找的重複模式。

+0

如果我理解他的權利,他正在尋找一個通用的「DataProvider 」,所以他不必反覆實施IList Get(int id) - 方法。 – stmax 2010-02-25 22:45:31

0

除非你想做一些超級醜陋的反射,你必須添加更多的元數據到你的類。理想情況下,將以接口的實現形式出現。有了這些信息,你實際上可以對Get方法的類型參數做些什麼。這是一個基本的示例,展示如何通過映射DataProviders來輸入參數。註冊表靜態類在使用前必須在某個時候初始化。

// generic mechanism through which the Get method can lookup a specific provider 
interface IDataProvider<T> { 
    List<T> Get(int id); 
} 

// implement the generic interface 
public class JobDataProvider : IDataProvider<Job> { 
    // existing stuff 
} 

// implement the generic interface 
public class PersondataProvider : IDataProvider<Person> { 
    // existing stuff 
} 

// this class holds the method originally desired  
public static class Helper { 
    public static List<T> Get<T>(int id) { 
    return Registry.Get<IDataProvider<T>>().Get(id); 
    } 
} 

// this functions as the glue/mapping between type parameters 
// and specific, concrete data providers 
public static class Registry { 
    private static Dictionary<Type, Func<object>> _entries; 

    public static T Get<T>() where T: class { 
    return _entries[typeof(T)]() as T; 
    } 

    public static void Register<T>(Func<T> item) { 
    _entries.Add(typeof(T),() => item() as object); 
    } 
} 

初始化代碼:

void Init() { 
    Registry.Register<IDataProvider<Job>>(() => new JobDataProvider()); 
    Registry.Register<IDataProvider<Person>>(() => new PersondataProvider()); 
} 

用法:

var job15 = Helper.Get<Job>(15); 
var person2 = Helper.Get<Person>(2); 
0

我還在hazzy在up_GetJobResult類的性質和up_GetPersonResult類。這些共享一個基類嗎?如果MyDataContext的結果總是來自相同的基類,那麼它會更容易一些:

/// <summary> 
/// Interface used on the individual classes that controls 
/// how the class will load it's data. 
/// </summary> 
public interface ILoadable 
{ 
/// <summary> 
/// Again, I did not know what type of return value comes back from MyDataContext 
/// If the results are always of the same type or if they derive from the same 
/// base class, then it makes it simpler. 
/// </summary> 
void Load(ResultBaseClass result); 
} 

public class Job : ILoadable 
{ 
public int Id { get; set; } 
public string Name { get; set; } 

public void Load(ResultBaseClass result) 
{ 
    var jobResult = result as up_GetJobResult; 
    if (jobResult == null) 
    return; 
    Id = jobResult.Id; 
    Name = jobResult.Name; 
} 
} 
public static class MyDataContext 
{ 
public static IList<ResultBaseClass> up_GetPerson(int id); 
public static IList<ResultBaseClass> up_GetJobResult(int id); 
} 

public class Person : ILoadable 
{ 
public int Id { get; set; } 
public string Name { get; set; } 
public string Surname { get; set; } 

public void Load(ResultBaseClass result) 
{ 
    var personResult = result as up_GetPersonResult; 
    if (personResult == null) 
    return; 
    Id = personResult.Id; 
    Name = personResult.Name; 
    Surname = personResult.Surname; 
} 
} 

public abstract class MyProvider<T> where T : ILoadable, new() 
{ 
/// <summary> 
/// Create a method only visible to derived classes which takes a delegate for the specific 
/// routine that should be called to retrieve data. 
/// </summary> 
protected List<T> Get(int id, Func<int, IList<ResultBaseClass>> getRoutine) 
{ 
    var result = new List<T>(); 
    foreach (var resultInstance in getRoutine(id)) 
    { 
    var item = new T(); 
    item.Load(resultInstance); 
    result.Add(item); 
    } 

    return result; 
} 
} 

public class JobDataProvider : MyProvider<Job> 
{ 
public List<Job> Get(int id) 
{ 
    return base.Get(id, MyDataContext.up_GetJobResult); 
} 
} 
public class PersonDataProvider : MyProvider<Person> 
{ 
public List<Person> Get(int id) 
{ 
    return base.Get(id, MyDataContext.up_GetPerson); 
} 
}