2017-02-22 8 views
0

이 문제의 상당 부분은 솔루션과 관련된 몇 가지 구성 요소에 대한 이해가 부족하다는 점에서 인정해야합니다. 필자는 Entity Framework, 코드 우선, 제네릭 형식에 완전히 익숙하지 않지만 세 가지 모두의 내부 동작은 여전히 ​​저에게 이상적입니다.Entity Framework의 일반 추가 메서드 - 문자열 이름에서 문제 유형 전달 유형

저는 코드 우선 프로젝트에서 "service"클래스에서 분리 된 "모델"클래스를 가지고 있으며 둘 다 일반화되어 있습니다. 나는 이 아니며이고 저장소 패턴을 사용하는 데는 여러 가지 이유가 있습니다. 내가하는 일의 대부분을 위해, 내가 잡은 구조가 아름답게 작동하고 있습니다. 이해하고 꽤 깨끗해 보입니다.

하지만 문제가있는 영역이 하나 있는데, 내 모델 클래스 유형 중 하나를 제네릭 매개 변수의 인스턴스에 일반 서비스 객체의 인스턴스에 전달할 수 있습니다. 모델 클래스.

(배경 : JSON 파일의 초기화 값을 사용하여 데이터베이스의 여러 테이블을 "시드"하기 때문에이 작업이 필요합니다.이 JSON 파일에는 모델 엔터티의 이름이 포함되어 있습니다. . 그 문자열 값을 얻을하고 데이터베이스 작업을 수행하는 일반 서비스 객체 유형으로 그에게 먹이를) 다음

는 관련 코드 조각은 다음과 같습니다

BaseEntity.cs 에서 내가 정상이 -level 인터페이스와 특정 모델 엔티티가 상속하는 많은 추상 클래스 :

namespace POST.API.Models 
{ 
    public interface IEntity 
    { 
     int Id { get; set; } 
    } 

    public abstract class BaseEntity { } 

    public abstract class Entity : BaseEntity, IEntity 
    { 
     public virtual int Id { get; set; } 
    } 

    public abstract class TypeEntity : Entity 
    { 
     public TypeDefinition Definition { get; set; } 
    } 
} 

BaseService.cs 에서 나는 특정 모델의 서비스 클래스가 상속되는 다른 인터페이스 및 더 많은 추상 클래스가있다. 여기에 삽입 작업을 수행하기 위해 일반화 된 하나의 구체적인 클래스가 있습니다.

namespace POST.API.Services 
{ 
    public interface IEntityService { } 

    public abstract class BaseEntityService<T> : IEntityService 
     where T : Models.BaseEntity 
    { 
     public T Fetch(int Id) 
     { 
      using (var Db = new PostDbContext()) 
      { 
       return Db.Set<T>().Find(Id); 
      } 
     } 

     public void Create(T Item) 
     { 
      if (Item != null) 
      { 
       using (var Db = new PostDbContext()) 
       { 
        DbSet Entity = Db.Set<T>(); 

        Entity.Add(Item); 
        Db.SaveChanges(); 
       } 
      } 
     } 

     public IEnumerable<T> All() 
     { 
      using (var Db = new PostDbContext()) 
      { 
       return (IEnumerable<T>)Db.Set<T>().ToList(); 
      } 
     } 
    } 

    public abstract class BaseTypeEntityService<T> : BaseEntityService<T> 
     where T : Models.TypeEntity 
    { } 

    public abstract class BasePropertyTypeEntityService<T> : BaseTypeEntityService<T> 
     where T : Models.PropertyTypeEntity { } 

    public abstract class BasePropertyEntityService<T> : BaseEntityService<T> 
     where T : Models.BaseEntity { } 

    public class TypeEntityService<T> : BaseTypeEntityService<T> 
     where T : Models.TypeEntity { } 

    #endregion 
} 

프레젠테이션과 관련없는 몇 가지 방법을 제거했습니다.

내가 이렇게 후 일부 행을 JSON 파일을 통해 뒤적 거리다 및 삽입하려면 다음 기본 클래스를 사용하려고 몇 가지 코드를 가지고, 내가 분명히 근본적인 무언가를 오해 한

 using (PostDbContext Db = new PostDbContext()) 
     { 
      string JsonString = System.IO.File.ReadAllText(JsonDataFile); 
      DataSet JsonDataSet = JsonConvert.DeserializeObject<DataSet>(JsonString); 
      foreach (DataTable Table in JsonDataSet.Tables) 
      { 
       Type EType = Type.GetType("POST.API.Models." + Table.TableName); 
       POST.API.Models.BaseEntity E = (POST.API.Models.BaseEntity)Activator.CreateInstance(EType); 
       Services.TypeEntityService<EType> S = new Services.TypeEntityService<EType>(); 

       foreach (DataRow Row in Table.Rows) 
       { 
        // Set properties of E and call Create method of S 
       } 
      } 
     } 

을하기 때문 코드는하지 않습니다 엮다. 이 코드 줄에 :

Services.TypeEntityService<EType> S = new Services.TypeEntityService<EType>(); 

... 나는 "형식 또는 네임 스페이스`ETYPE은 '을 (를) 찾을 수 없습니다."컴파일러는 불평으로, ETYPE 내 참조에 오류가

분명히 그 참조는 런타임에 평가할 수 없습니다. 그렇다면 지구상에서 어떻게해야하는지 궁금합니다. 모든 관련 주제는 만족스런 대답을 얻지 못하는 것 같습니다. 적어도 내 자신의 구현의 맥락에서 의미가있는 방식은 아닙니다.

답변

1

아래와 같이 액티베이터로 Services.TypeEntityService<EType>을 만들어야합니다.

  Type EType = Type.GetType("POST.API.Models." + Table.TableName); 
      Type[] typeArgs = { EType }; 
      var generic = typeof(Services.TypeEntityService<>).MakeGenericType(typeArgs); 
      var S = Activator.CreateInstance(generic); 
+0

오케이 ... 이것은 어떤면에서 나에게 더 의미가 있으며 실제로 하나의 문제를 해결합니다. 그러나 나는 여전히 E와 S 변수의 프로퍼티와 메소드를 참조 할 수 없다. 전체적인 점은 ... 나는 실제로 E의 프로퍼티를 설정하고 새로운 프로 시저를 추가하기 위해 S의 Create 메소드를 호출 할 수 없다. E ... –

+0

나는 E 코드를 만들지는 않았지만 거기에서'var method = S.GetMethod ("MyMethodName");'그리고'var result = method '에서 메소드를 호출하기 위해 리플렉션을 사용해야 할 것이다. .Invoke (generic, new object [] {E}); ' –

+0

S가 GetMethod를 사용할 수 없다는 점을 제외하면 최소한 코드가 구조화 된 방식으로 ... S는 Equals, GetType, GetHashCode 및 ToString 만 사용할 수 있습니다. , var로 ... –

1

그럼 당신은 EType 입력 System.Type의 수 변수가 있습니다. Type 인스턴스는 제네릭 형식에 사용할 수 없습니다. Services.TypeEntityService 구현을 변경하여 런타임 유형 인스턴스 (예 : TypeEntityService (System.Type type))를 가져와야합니다.

편집 : 또는 실제로 다른 답변 상태처럼 Reflection을 사용하여 Type 인스턴스에서 일반 매개 변수를 작성하십시오. 그것은 더 의미가 있습니다.