2

私のコードの下に見つけてください。Employee クラスは IEmployee インターフェイスを実装します。

    namespace MiddleWare.ServiceContracts

    {
        [ServiceContract(Namespace = "http://mywebsite.com/MyProject")]

        public interface IMiscellaneous
        {
           [OperationContract]
            [ServiceKnownType(typeof(MiddleWare.Classes.Employee))]
            IEnumerable<IEmployee> Search_Employee
            (string SearchText);

    }


    namespace MiddleWare.ServiceClasses
    {
       public class Miscellaneous : IMiscellaneous
        {
           public IEnumerable<IEmployee> Search_Employee
            (string SearchText)
            {
               List<IEmployee> emp = new List<IEmployee>();

               IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(IEmployee));  
               TempObject.EmployeeId = "12345678";

               emp.Add(TempObject);
              return emp;
           }
       }
    }

表示されているように、上記のコードはコンパイルされますが、インターフェイス インスタンスを作成できないため機能しません。

IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(Employee));

次に、このクラスはインターフェイスだけでなくクラスにも依存します...ある晴れた日の従業員クラスが従業員2になると仮定すると、2つの場所でコードが変更されます.. 1)[ServiceKnownType(typeof(MiddleWare.Classes.Employee2))]

2)IEmployee TempObject = (IEmployee)Activator.CreateInstance(typeof(Employee2));

それは避けたい。IOperationBehavior の実装で何かを行うことはできますか、またはこれを達成する Ninject の方法はありますか、それとも不可能を達成しようとしていますか?

4

4 に答える 4

2

設計変更を検討する - ファクトリ パターンを使用して、従業員のインスタンスを作成します。

public EmployeeFactory : IEmployeeFactory 
{
  public IEmployee CreateEmployee() 
  {
    return new Employee();
  }
}

ミドルウェアから Factory への依存関係を導入すると、新しい IEmployee の作成は次のようになります。

public class Miscellaneous : IMiscellaneous 
{ 
    private readonly IEmployeeFasctory _employeeFactory;

    public class Miscellaneous(IEmployeeFactory employeeFactory)
    {
        _employeeFactory = employeeFactory;
    }

    public IEnumerable Search_Employee (string searchText) 
    { 
       List employees = new List();
       IEmployee employee = _employeeFactory.CreateEmployee();  
       employee.EmployeeId = "12345678";
       employees.Add(TempObject);
       return employees;
}

そして、EmployeeFactory を Miscellaneous に注入できます。そして、ある日 Employee が非推奨になり、Employee2 が登場した場合は、ファクトリを変更するだけです!

于 2011-11-22T11:46:15.947 に答える
1

rich.okelly が別の回答で指摘しているように、 Service ではなく Entity であるため、インターフェイスIEmployeeFactoryのインスタンスを作成するために使用する必要があります。IEmployeeIEmployee

一方、インターフェースは Service であるため、 Constructor InjectionIEmployeeFactoryを使用してサービス クラスに注入する必要があります。WCF でのコンストラクター インジェクションの有効化についての記事を次に示します。

于 2011-11-22T11:59:09.643 に答える
1

チーム内でディスカッションを行いました。

1) コンストラクター ベースの実装は快適ではありません。サービスは IIS でホストされ、Web 参照として消費されます。クライアント システムに、その他のクラス呼び出しで FactoryImplementatedObjects を提供するように要求できません。

2) エンティティ ベースのファクトリも完全に正確ではありません。プロジェクトで Employee、Material、Project、Location、Order などの特定のエンティティが 20 個あるとしたら、20 個のファクトリが必要です。また、Miscellaneous クラスにはいくつかのカスタム コンストラクタがあります。特定の契約コールをサポートする..

私は機能しているシステムを準備しており、DIは素晴らしいレベルに達していますが、私はOOPSをだましているように感じます..心から正しいとは感じません..しかし、間違っていると反論することはできません..チェックしてコメントをお知らせください. .

これで、他のすべてのエンティティのベースとなる IEntity インターフェイスができました。

namespace BusinessModel.Interfaces
{
    public interface IEntity
    {
        string EntityDescription { get; set; }
    }
}

今後、すべてがこれを実装します。

namespace BusinessModel.Interfaces
{
    public interface IEmployee : IEntity
    {
        string EmployeeId { get; set ; } 
    }
}

namespace BusinessModel.Interfaces
{
    public interface IProject : IEntity
    {
        string ProjectId { get; set; }
    }
}

など..(インターフェイスを実装するインターフェイス..絶対にばかげている、不正行為をしているが機能している)

次に、Enum 型がすべてのエンティティのリストを持つように宣言されます...

namespace MiddleWare.Common
{
    internal enum BusinessModel
    {
        IEmployee,
        IProject
    }
}

今後はビジネス モデルの一部と見なされる DI ヘルパー クラスが作成され、それに対する変更 (実装、ネーミングなど) はビジネス シフトと見なされます。 (これも回避できるのか??)

namespace MiddleWare.Common
{
    internal sealed class DIHelper
    {
        internal static IEntity GetRequiredIEntityBasedObject(BusinessModel BusinessModelObject)
        {
            switch (BusinessModelObject)
            {
                case BusinessModel.IEmployee:
                    return new Employee();
            }

            return null;
        }
    }
}

機能は自明です...

では、最後に、契約と実装...

namespace MiddleWare.ServiceContracts
{
[ServiceContract(Namespace = "http://mywebsite.com/MyProject")] 
public interface IMiscellaneous
    {
    [OperationContract]
    [ServiceKnownType(typeof(MiddleWare.Classes.Employee))]
    IEnumerable<IEmployee> Search_Employee
        (string SearchText);
    }
}

namespace MiddleWare.ServiceClasses
{
    public class Miscellaneous : IMiscellaneous
    {
        public IEnumerable<IEmployee> Search_Employee
            (string SearchText)
        {
            List<IEmployee> IEmployeeList = new List<IEmployee>();

            IEmployee TempObject = (IEmployee)DIHelper.GetRequiredIEntityBasedObject(MiddleWare.Common.BusinessModel.IEmployee);
            TempObject.EmployeeId = "12345678";

            IEmployeeList.Add(TempObject);
            return IEmployeeList;
        }
    }
}

あなたは何を言っていますか??私のチームは満足しています:)

于 2011-11-23T09:03:56.960 に答える
0

更新された要件から、この質問にはDIに関連するものは何もありません...

したがって、サービス契約の既知のタイプのサービスに基づいてタイプを作成するには、次のようにします。

public class EntityLoader<TServiceContract>
    {
        private static readonly HashSet<Type> ServiceKnownTypes = new HashSet<Type>();
        static EntityLoader()
        {
            var attributes = typeof(TServiceContract).GetMethods().SelectMany(m => m.GetCustomAttributes(typeof(ServiceKnownTypeAttribute), true)).Cast<ServiceKnownTypeAttribute>();
            foreach (var attribute in attributes)
            {
                ServiceKnownTypes.Add(attribute.Type);
            }
        }

        public TEntity CreateEntity<TEntity>()
        {
            var runtimeType = ServiceKnownTypes.Single(t => typeof(TEntity).IsAssignableFrom(t));
            return (TEntity)Activator.CreateInstance(runtimeType);
        }
    }

その場合、次のように使用できます。

    [ServiceContract(Namespace = "http://mywebsite.com/MyProject")]
    public interface IMiscellaneous
    {
        [OperationContract]
        [ServiceKnownType(typeof(Employee))]
        IEnumerable<IEmployee> SearchEmployee(string SearchText);
    }

    public class Miscellaneous : IMiscellaneous
    {
        private readonly EntityLoader<IMiscellaneous> _entityLoader = new EntityLoader<IMiscellaneous>();
        public IEnumerable<IEmployee> SearchEmployee(string SearchText)
        {
            List<IEmployee> employees = new List<IEmployee>();

            IEmployee employee = _entityLoader.CreateEntity<IEmployee>();
            employee.EmployeeId = "12345678";

            employees.Add(employee);
            return employees;
        }
    }

明らかに、上記のコードは、すべてのサービスエンティティにパブリックパラメーターのないコンストラクターが含まれ、各インターフェイスを実装するServiceKnownTypeが1つだけであることを前提としています。

于 2011-11-23T10:05:43.000 に答える