2010-10-13 34 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它返回的是微不足道的。