2012-06-19 5 views
1

제네릭 호출에서 해당 변수를 변수로 사용할 수있는 방법을 파악하려고합니다. 아래의 호출에서는 "DAL.Account"유형을 사용하고 정상적으로 작동합니다.일반 매개 변수로 속성 유형

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

"DAL.Account"대신 변수를 전달할 수 있도록 변경하고 싶습니다. 이 같은 것이 있지만 유형으로 속성을 전달할 수 없으므로 작동하지 않습니다.

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; 
     } 
    } 
} 

답변

2

일반적인 유형을 인스턴스화하려고합니다. 일부 정보는이 여기에 (3)의 용량의 목록을 인스턴스화하는 방법을 보여주는 간단한 예입니다 here

를 찾을 수 있습니다 당신은 당신이 유형을 모를 때 제네릭을 만들 호출 할 수있는 방법은 다음과 같습니다

당신의 예에서

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)로 교체 : 여기

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; 
    } 

그리고 당신에게 예를 방법을 보여줍니다 몇 가지 예제 코드를 작동합니다. 이것은 당신이 전달하는 타입의 일반 테이블을 리턴 할 것입니다. 물론 당신은 물론 메소드를 적절하게 구현해야합니다 (생성자 args를 처리하고, List to Table 등을 변경해야합니다).

0

이 방법을 약간 변경하고 대신 EntityType 속성 대신 generics를 사용해야한다고 생각합니다. 아마도 다음의 내용을 따르는 어떤 것 :

// 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> 
{ 
    ... 
} 
관련 문제