基于给定的Type变量从列表中提取实例

时间:2010-10-13 18:11:11

标签: c# types

我担心这对于一个简单的问题来说将是一个很大的设置。至于答案的复杂性,我担心我可能会遇到什么......

我正在构建一个应用程序,用于帮助将数据从具有一个表结构的源数据库转换为具有不同结构的目标数据库。目标数据库已经包含数据,因此当插入到目标时,进程必须能够从源维护基于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>的实例表示。 TransformationTypeSourceType的每个映射都会有TargetType,其中每个映射都可能是DataContext中的一个类。每个源数据库表将有一个,但其中许多表可能映射到单个目标数据库表。

使用IDataSetStorable作为标记界面可以在EntityList<>的实例中存储具有许多不同子类型的InMemoryDataSet

在从源DB转换任何项目期间,如果我们知道其外键的相应目标数据库ID,则只能将其插入目标数据库。为此,代码将从源数据库中找到所有依赖项,并在尝试转换所考虑的项目之前对其进行转换。递归地,这应该确保插入到目标数据库中的第一个东西没有依赖关系,获取它们的新ID,然后在插入依赖它们的东西时可以查找它们。

InMemoryDataSet的实例将提供查找工具,应该传递ID(来自源数据库)和类型Type的参数,表示处理的TransformationType改变被查找项目的类型。

示例:Table1有两个字段idtable2_id,后者引用Table2及其字段id。查询调用将是(有点伪代码):

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

然后entity应该是Table2TransformationType类型(最终从AbstractDataEntity继承),并且代表来自Table2的行,其ID匹配传递给方法。< / p>

最后,问题是:

FindEntity()方法中,如何找到是否存在EntityList<whatever the passed type was>?我的想法是使用类似的东西:

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

简单的问题!但我不知道我最后能做到这一点:(

3 个答案:

答案 0 :(得分:1)

您需要检查:

  1. 如果当前项Type的{​​{1}}代表通用类型
  2. 如果该通用类型代表entityList
  3. 如果该类型的泛型参数是传入的类型
  4. 试试这个:

    EntityList<>

    编辑:从错误的类型中获取通用参数。固定的。

答案 1 :(得分:1)

好的,设法使用一点反射来完成这项工作。 Kirk Woll让我开始寻找合适的地方,但最终解决方案没有使用他的建议。 public T RetrieveEntity(string id)课程中还有一个额外的方法EntityList<T>,以便在使用Dictionary时更方便地通过键从Type.GetMethod()获取单个项目:< / p>

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是微不足道的。

答案 2 :(得分:0)

使用Linq:

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