2017-11-16 1 views
1

내가 외부 DLL에 대한 참조가있는 프로그램이 있습니다로드 다른 라이브러리를 동적으로

magic.externalFunctions.nosql.dll 

이를 : 나는 대신 다음해야 할 수도 있습니다

magic.externalFunctions.sql.dll 

대상 시스템에 따라 DLL은 동일한 기능을 제공하는 외부 라이브러리입니다. 공용 메소드와 속성조차 동일합니다. 그러나 에는 인터페이스 또는 기본 클래스가 결합되어 있지 않습니다.

이제 대상 시스템에 따라이 두 라이브러리를 선택해야합니다. 반사의 과도한 양을 사용하지 않고이 문제를 해결하기 위해 어떤 방법이 있나요

public class DoDatabaseStuff() { 
    private IMagic _magic 
    public DoDatabaseStuff(bool useNoSql) { 
     if (useNoSql) { 
     _magic=new SqlMagic(); 
     } else { 
     _magic=new NoSqlMagic(); 
     } 
     myTable=_magic.Table.Create("CustomerTable"); 
     myTable.Columns.Add(typeof(int),"ID"); 
     myTable.Columns.Add(typeof(string),"Name"); 
    } 
} 

: 그들은 에게 공통의 인터페이스를했을 경우 내가 좋아하는 일을 할 것인가? 나는 여전히 myTable.Columns.Add() 대신 tableType.GetMethod("Add").Invoke()... 대신

과 같은 것을 사용하고 싶다. 다른 빌드 구성을 사용하는 csproj에서 조건을 사용하고 싶지는 않다. 이론적으로는 작동하지만 csproj가 자동으로 변경 될 때마다 오류가 발생합니다 (예 : 너겟 패키지 업데이트)

+0

동일한 작업을 수행하는 여러 라이브러리간에 전환하고자하는 이유는 무엇입니까? 확실히 비효율적 인 방법이고 종속성이 증가합니다 – jasttim

+0

하지만 이렇게해야 할 경우 헬퍼 메서드를 만들어서 SQL 라이브러리를 호출하고 NON SQL 라이브러리를 호출 할 수 있습니다 – jasttim

+0

우리는 프로그램을 두 개의 다른 플랫폼에 설치하십시오. 현재 우리는 동일한 소스 파일을 포함하지만 서로 다른 참조를 포함하는 두 개의 프로젝트가 있지만 구조가 변경되면 오류의 큰 원인이됩니다. 같은 문제를 해결하기 위해 두 가지 다른 git 브랜치를 만들려고했습니다. 여기에서 가장 중요한 문제는 EXTERNAL 라이브러리입니다. 이것이 우리 자신의 코드라면 다른 방식으로했을 것입니다. –

답변

5

변경할 수없는 불량 디자인에 직면했을 때 좋은 방법은 귀하의 코드에서 디자인하십시오. 이 경우 외부 어셈블리가 부족한 공용 ​​인터페이스를 만들어야 함을 의미합니다.

어댑터를 사용하여 초기 디자인 결함을 코드 코어 밖으로 유지할 수있는 통합 인터페이스를 제공 할 수 있습니다. 당신은 원래의 클래스에 대한 추상화를 만들기 시작

당신이 액세스하려는 : 당신은 각각의 어댑터를 반환 할 수 있습니다

class SqlMagicAdapter : IMagic { 
    SqlMagic m_innerMagic = new SqlMagic(); 

    ITable CreateTable(string name) { 
     return new SqlTableAdapter(m_innerMagic.Table.Create(name)); 
    } 
} 

class SqlTableAdapter : ITable { 
    SqlTable m_innerTable; 
    public SqlTableAdapter(SqlTable innerTable) { 
     m_innerTable = innerTable; 
    } 
    void AddColumn(Type type, string name) { 
     m_innerTable.Columns.Add(type, name); 
    } 
} 

class NoSqlMagicAdapter : IMagic { 
    NoSqlMagic m_innerMagic = new NoSqlMagic(); 

    ITable CreateTable(string name) { 
     return new NoSqlTableAdapter(m_innerMagic.Table.Create(name)); 
    } 
} 

class NoSqlTableAdapter : ITable { 
    NoSqlTable m_innerTable; 
    public NoSqlTableAdapter(NoSqlTable innerTable) { 
     m_innerTable = innerTable; 
    } 
    void AddColumn(Type type, string name) { 
     m_innerTable.Columns.Add(type, name); 
    } 

공장 방법으로 :

public interface IMagic { 
    ITable CreateTable(string name); 
} 

public interface ITable { 
    void AddColumn(Type type, string name); 
} 

는 그런 다음 어댑터를 제공

public static class MagicFactory { 
    public static IMagic GetMagic(bool useNoSql) { 
     if (useNoSql) { 
      return new NoSqlMagic(); 
     } 
     else { 
      return new SqlMagic(); 
     } 
    } 
} 

핵심 코드는 t 그는 공장에 의해 반환 된 추상화 :

public class DoDatabaseStuff() { 
    private IMagic _magic 
    public DoDatabaseStuff(bool useNoSql) { 
     _magic = MagicFactory.GetMagic(useNoSql); 
     ITable myTable = _magic.CreateTable("CustomerTable"); 
     myTable.AddColumn(typeof(int), "ID"); 
     myTable.AddColumn(typeof(string), "Name"); 
    } 
} 

는 예를 들어, 장점은 또한 미래의 변화에 ​​대한 준비가되어 있다는 것입니다 이전의 것들과 호환되지 않는 또 다른 업데이트 된 외부 라이브러리를 추가했다. 핵심 코드를 변경하지 않고도 이러한 새로운 기능을 쉽게 지원할 수 있습니다.

관련 문제