2016-12-27 8 views
1

일반 저장소 패턴과 단위 작업을 구현했습니다. 나는 기본 패턴을 사용하고 그들은 잘 작동합니다. 프로젝트에서 필자는 모든 테이블에는 길고 긴 텍스트가 포함 된 여러 필드가 있으며 사용자는 그 중 하나를 선택하여 열 수 있어야한다는 요구 사항이 있습니다. 다르게 이름이 지정된 각 필드가 리플렉션으로 전원 제네릭을 사용하기로 결정한 것처럼 테이블 이름과 필드 이름을 반환하고 반환하는 메서드를 작성했습니다. 방법은 일반 저장소 클래스에, 나는 이런 모습을 쓴, 내가 도움 EF와 테이블의 모델 클래스를 creted 제대로리플렉션을 사용하여 기본 클래스에서 메서드 호출

public interface IRepository<T> where T : class 
    { 
     //other methods 

     string GetPropertyByName(int id, string property); 
    } 

    public class Repository<T> : IRepository<T> where T : class 
    { 
     // other methods. add, edit, delete... 

     public string GetPropertyByName(int id, string property) 
     { 
      T model = this.Get(id);   
      var obj = model.GetType().GetProperty(property).GetValue(model, null); 
      return obj != null ? obj.ToString() : null; 
     } 
    } 

일 것 같다. 일부 테이블은 genric 저장소에 직접 바인딩하는 반면, 다른 테이블은 추가적인 메소드가 필요하기 때문에 별도의 인터페이스와 구현이 있습니다. 예 :

public interface ICompanyRepo : IRepository<COMPANY> 
{ 
    //some methods 
} 

public class CompanyRepo : Repository<COMPANY>, ICompanyRepo 
{ 
    //implementations of interface methods 
} 

그리고 UOW 구현 :

public interface IUnitOfWork 
{ 
    ICompanyRepo Company { get; }   
    IRepository<CURRENCY> Currency { get; }   
} 

public class UnitOfWork : IUnitOfWork 
{ 
    static DBEntities _context; 
    private UZMEDEXPORTEntities context 
    { 
     get 
     { 
      if (_context == null) 
       _context = new DBEntities(); 
      return _context; 
     } 
    } 
    public UnitOfWork() 
    { 
     _context = context; 
     Company = new SP_CompanyRepo(); 
     Currency = new Repository<CURRENCY>(); 

    } 

    public ICompanyRepo Company { get; private set; } 
    public IRepository<CURRENCY> Currency { get; private set; } 
} 

내가 비즈니스 계층에 GetPropertyByName() 메소드를 호출에 문제가 있습니다. System.Reflection.TargetException을 반환

public string GetHistory(string tableName, string fieldName, int id) 
    { 
     var prop = unitOfWork.GetType().GetProperty(tableName); 
     MethodInfo method; 
     method = prop.PropertyType.GetMethod("GetPropertyByName"); //try to find method 
     if(method == null) //if method not found search for interface which contains that method 
      method = prop.PropertyType.GetInterface("IRepository`1").GetMethod("GetPropertyByName"); 
     var res = method.Invoke(prop, new object[] { id, fieldName }); 
     return (string)res; 
    } 

: 이 시도. 내가 아는 한 문제는 단위 작업 구현이다. 내 호출 메소드에서 "prop"는 인터페이스 유형 (ICompanyRepo)이지만 invoke의 대상은 인터페이스 구현 클래스 여야합니다 (이 경우 "CompanyRepo"). implementationetion 클래스의 유형을 식별하는 방법을 찾지 못하고이 문제를 해결할 수 없습니다. 어떤 도움도 충당 됨

+1

사이드 노트 : "일반 방법"은 C#에서 매우 구체적인 의미를 가지고 있습니다 - 포스트에 표시된 코드는 일반적인 방법을 보여주지 않습니다. 메서드 (예 :'Foo ()') 또는 다른 단어를 대신 사용하십시오 ... –

+0

메서드는 제네릭 클래스, 리포지토리 안에 있으므로 나는 그것이 너무 일반 메서드를 호출 올바른지 생각. Anywat 당신이 맞아, 그 부분을 편집했습니다 @AlexeiLevenkov –

+1

나는 본다. 코드 게시에 대한 [MCVE] 지침을 읽으십시오. TEntity가 특정 유형 (이상한 이름 지정 규칙이있는)인지 또는 게시물에 제공된 코드를 기반으로하는 일반 유형의 매개 변수인지를 알 수있는 방법이 없습니다. –

답변

0

이것이 최선의 선택이 아닌 것은 확실하지만, ToExpando() 확장자를 사용하여 해결 된 문제는 here입니다. 이 확장을 통해 루프는 unitofwork의 모든 속성을 던지고 이름으로 필요한 속성을 찾습니다.

var propValue = unitOfWork.ToExpando().Single(x => x.Key == prop.Name).Value; 
var res = method.Invoke(propValue, new object[] { id, fieldName }); 

이제 메소드가 올바르게 호출됩니다. 거기에 깨끗한 솔루션이있을 수 있으며, 여전히 이것을 찾으려고합니다. 지금은이 솔루션을 사용할 것이며 반사음, 다이내믹 및 제네릭에 대해 많이 읽고 연습해야한다는 것을 깨달았습니다. PS 중요한 노트와 조언에 대한 Alexei에 대한 특별 감사 덕분에

관련 문제