1

Generics呼び出しでTypeの変数を取得する方法を理解しようとしています。以下の呼び出しでは、タイプ「DAL.Account」を取り、正常に機能します。

var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");

「DAL.Account」の代わりに変数を渡すことができるように変更したいと思います。このようなものですが、プロパティをTypeとして渡すことができないため、機能しないことはわかっています。

ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray())

以下は、私がやろうとしていることを説明していると思うコードのシェル部分です。ジェネリックは私の強いスーツではないので、私はいくつかの助けを探しています。とにかくこれを実現できることはありますか?

//Stores a "Type" that indicates what Object is a Criteria for.
public class AccountCriteria : IGeneratedCriteria
{
    ...

    public Type EntityType
    {
        get {return typeof(DAL.Account);}
    }
}

//I have added a function to the DataContext called "GetTable"
// And then used it as an example in a Console App to test its functionality.
public class ADRPDataContext : NHibernateDataContext
{
    ...

    public CodeSmith.Data.NHibernate.ITable<T> GetTable<T>() where T : EntityBase
    {
         var tb = new CodeSmith.Data.NHibernate.Table<T>(this);
         return tb;
    }
}

// console application that uses DataContext.GetTable
class Program
{
    static void Main(string[] args)
    {
        using (var ctx = new ADRPDataContext())
        {
            var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");
        }
    }
}

//ExistsCommand class that uses the EntityType property of the Critera to generate the data.
public class ExistsCommand
{
    private IGeneratedCriteria Criteria { get; set; }

    protected override void DataPortal_Execute()
    {
        using (var ctx = new DC.ADRPDataContext())
        {
            //This was my first attempt but doesn't work becuase you can't pass a property in for a Type.
            //But I can figure out how to write this so that it will work.
            Result = ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray()).Count() > 0;
        }
    }
}
4

2 に答える 2

2

ジェネリック型をインスタンス化しようとしています。いくつかの情報はここで見つけることができます

これは、容量3のリストをインスタンス化する方法を示す簡単な例です。タイプがわからない場合に呼び出してジェネリックを作成できるメソッドを次に示します。

public static Object CreateGenericListOfType(Type typeGenericWillBe)
    {
        //alternative to the followin:
        //List<String> myList = new List<String>(3);


        //build parameters for the generic's constructor (obviously this code wouldn't work if you had different constructors for each potential type)
        object[] constructorArgs = new Object[1];
        constructorArgs[0] = 3;


        //instantiate the generic.  Same as calling the one line example (commented out) above. Results in a List<String> with 3 list items
        Type genericListType = typeof(List<>);
        Type[] typeArgs = { typeGenericWillBe };
        Type myNewGeneric = genericListType.MakeGenericType(typeArgs);
        object GenericOfType = Activator.CreateInstance(myNewGeneric, constructorArgs);


        return GenericOfType;
    }

そして、ここにサンプルメソッドが機能することを示すいくつかのサンプルコードがあります:

List<String> Strings = (List<String>)InstantiateGenericTypeWithReflection.CreateGenericListOfType(typeof(String));

        //demonstrate the object is actually a List<String> and we can do stuff like use linq extensions (isn't a good use of linq but serves as example)
        Strings.Add("frist");
        Strings.Add("2nd");
        Strings.Add("tird");
        Console.WriteLine("item index 2 value: " + Strings.Where(strings => strings == "2").First());

あなたの例では、をに置き換えGetTable<Criteria.EntityType>()ますCreateGenericTableOfType(Criteria.EntityType)。これにより、渡したタイプのジェネリックテーブルが返されます。もちろん、メソッドを適切に実装する必要があります(コンストラクター引数の処理、リストのテーブルへの変更など)。

于 2012-08-08T15:47:34.203 に答える
0

これを行う方法を少し変更し、代わりにEntityTypeプロパティの代わりにジェネリックを使用する必要があると思います。おそらく、次のようなものです。

// Create an abstract class to be used as the base for classes that are supported by
// ExistsCommand and any other classes where you need a similar pattern
public abstract class ExtendedCriteria<T> : IGeneratedCriteria
{
    public ExistsCommand GetExistsCommand()
    {
        return new ExistsCommand<T>(this);
    }
}

// Make the non-generic ExistsCommand abstract
public abstract class ExistsCommand
{
    protected abstract void DataPortal_Execute();
}

// Create a generic sub-class of ExistsCommand with the type parameter used in the GetTable call
// where you were previously trying to use the EntityType property
public class ExistsCommand<T> : ExistsCommand
{
    protected override void DataPortal_Execute()
    {
        using (var ctx = new DC.ADRPDataContext())
        {
            Result = ctx.GetTable<T>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray()).Count() > 0;
        }
    }

}

// Derive the AccountCriteria from ExtendedCriteria<T> with T the entity type
public class AccountCriteria : ExtendedCriteria<DAL.Account>
{
    ...
}
于 2012-06-20T00:22:04.093 に答える