2010-10-13 93 views
1

我擔心這將是一個簡單的問題,一個很大的設置。至於答案的複雜性,我怕什麼,我可能會進入...提取實例

我建立將被用於幫助從源數據庫具有一個表結構,不同的轉換數據到目標數據庫的應用程序結構體。目標數據庫將包含的數據已經,因此處理必須能夠插入到目標,在新插入的項目將獲得新的ID時,維持從源頭基於ID的關係。假設每個源表都可以轉換爲單個目標表。

最小碼,必要的類/接口結構:

public interface IDataSetStorable { } 

public class InMemoryDataSet : List<IDataSetStorable> 
{ 
    public AbstractDataEntity FindEntity(string id, Type type) 
    { 
     // The question will be about this method 
     return new object() as AbstractDataEntity; 
    } 
} 

public class EntityList<T> : Dictionary<string, T>, IDataSetStorable where T : AbstractDataEntity 
{ 
    public void AddEntity(T entity) 
    { 
     this.Add(entity.ID, entity); 
    } 
} 

public abstract class AbstractDataEntity 
{ 
    public string ID { get; set; } 
} 

public abstract class DataItem<S, T> : AbstractDataEntity { } 


// There will be a set of these three classes per source DB table 
public class SourceType { } 
public class TargetType { } 
public class TransformationType : DataItem<SourceType, TargetType> { } 

InMemoryDataSet保持的表中,通過(例如)EntityList<TransformationType>實例表示。會有的SourceType每個映射到TargetType,其中每個的那些可能是從一個DataContext的類的TransformationType。每個源數據庫表將有一個,儘管其中許多表可能映射到單個目標數據庫表。

使用IDataSetStorable作爲標記接口允許在InMemoryDataSet的實例內存儲具有許多不同亞型的EntityList<>

在從源數據庫的任何項目的改造,它只能插入到目標數據庫,如果我們知道它的外鍵適當的目標-DB的ID。爲此,代碼將從源數據庫中查找所有依賴項,並在嘗試轉換正在考慮的項目之前對其進行轉換。遞歸,這應該能保證插入到目標數據庫的第一件事情有沒有依賴關係,讓他們的新的ID,並且將依賴於他們的東西時就可以進行查找。

InMemoryDataSet實例將提供查找設施,這應傳遞的ID(從源DB)和Type類型的參數,表示與變換項的類型交易的TransformationType被查找。

的實施例:Table1具有兩個字段,idtable2_id,後者引用Table2,其場id。查找呼叫將是(有點僞-Y):

var entity = myDataSet.FindEntity([table1.table2_id], typeof(Table2TransformationType)); 

然後entityTable2TransformationType類型(從AbstractDataEntity最終繼承)的,並且將來自與Table2 ID匹配傳遞給該方法表示的行。

最後,到了一個問題:

FindEntity()方法,我怎麼能找到,如果有一個EntityList<whatever the passed type was>禮物?我的想法是使用類似的東西:

foreach (var entityList in this) 
{ 
    // work out if entityList is an EntityList<passed-in type>; 
} 

簡單的問題!但我不知道我該怎麼做這最後一部分:(

回答

1

您需要檢查:

  1. 如果Type當前項目entityList代表通用類型
  2. 如果該通用類型表示EntityList<>
  3. 如果該類型的泛型參數是傳入的YPE

試試這個:

if (entityList.GetType().IsGenericType && 
    entityList.GetType().GetGenericTypeDefinition() == typeof(EntityList<>) && 
    entityList.GetType().GetGenericArguments()[0] == type) 
{ 
    ... 
} 

編輯:是越來越通用的參數出現在錯誤的類型。固定。

+0

絕對到達那裏。前兩個陳述評估爲「真實」,但第三個陳述並非如此。看起來'entityList.GetType().GetGenericTypeDefinition().GetGenericArguments()[0])從'EntityList '的原始聲明中返回'T',而不是'EntityList'創建的特定類型。有沒有嘗試將'entityList'變量轉換爲'EntityList <傳入類型>'的方法,如果它不合適會拋出異常? – 2010-10-14 10:05:56

+0

@Matt,我的道歉,我應該先測試一下。我更新了答案,但得到了錯誤類型的泛型參數。現在應該工作。 – 2010-10-14 13:48:19

+0

釘上它+1,並標記爲已接受。我自己的答案是有效的,但是你的答案早一些,而且比依靠Invoke的一個轉換異常更加整潔! – 2010-10-15 15:47:05

0

使用LINQ:

  Dictionary<string, Type> a = new Dictionary<string, Type>(); 
     var allOfMyType = a.Where(x=> (x.Value.Name == "MyType")); 
1

好的,設法讓這項工作使用了一點思考。柯克沃爾讓我開始尋找正確的地方,但最終解決方案沒有使用他的建議。使用Type.GetMethod()時有一個附加的方法,public T RetrieveEntity(string id),在順序EntityList<T>類,使其更容易獲得單個項目出Dictionary通過關鍵的:

public class EntityList<T> : Dictionary<string, T>, IDataSetStorable where T : AbstractDataEntity 
{ 
    public void AddEntity(T entity) 
    { 
     this.Add(entity.ID, entity); 
    } 
    public T RetrieveEntity(string id) 
    { 
     return this[id]; 
    } 
} 

然後我們有FindEntity(string id, Type type)方法的膽量:

public class InMemoryDataSet : List<IDataSetStorable> 
{ 
    public AbstractDataEntity FindEntity(string id, Type type) 
    { 
     // Make an instance of the passed-in type so that invoking 
     // TryGetValue will throw an exception if operating on an 
     // EntityList which is not of the correct type. 
     var sample = type.GetConstructor(new Type[]{}).Invoke(new object[]{}); 
     foreach (var entityList in this) 
     { 
      try 
      { 
       // This doesn't manage to set sample to the found entity... 
       bool idFound = (bool)entityList.GetType().GetMethod("TryGetValue").Invoke(entityList, new object[] { id, sample }); 
       if (idFound) 
       { 
        // So we dig it out here with the method added to EntityList<> 
        sample = entityList.GetType().GetMethod("RetrieveEntity").Invoke(entityList, new object[] { id }); 
        return (AbstractDataEntity)sample; 
       } 
      } 
      catch (Exception ex) 
      { 
       // Likely some kind of casting exception 
      } 
     } 
     return null; 
    } 
} 

在調用FindEntity()點,我們知道需要的類型是什麼,所以鑄造AbstractDataEntity它返回的是微不足道的。