エクスプレッションツリーを使用して、アクセス者にロールオブジェクトを直接実行させる方法

8251 ワード

以前、『業務分析三次元度(シーン+ロール+時間)理論』のソフトウェア設計について議論したとき、シーン内のアクセス者に対して、シーンライセンスの役割を動的に付加し、アクセス者によってロールメソッドを実行する方法について、以下の実装方法を採用した.
Actor.ActAs<IRole>().Function(Para para);

この方式は本質的に、ActorをIroleインタフェースのインスタンスオブジェクトに変換し、メソッドアクセスを行うが、これによりキャラクタオブジェクトが露出し、例えば、このように使用を継続することができる.
IRole role=Actor.ActAs<IRole>();
role.Fun1();
role.Fun2("abc");

これで見ると、roleとActorが2つの対象になってしまい、なんだか割れ目になってしまいます.今日、式ツリーを使用して、より美しいスキームを実現します.
まず、キャラクタオブジェクトとビジターオブジェクトのインタフェースを定義します.
 public interface IActor
    {
        string Name { get; }
    }
    public interface IRole
    {
        IActor Actor { get; set; }
    }

そして動物のキャラクターインタフェースを定義し、歩くことと食べ物を食べる本能的な方法を持っています.
 public interface IAnimal:IRole
    {
        void Move();
        int Eat(string food);
        
    }

次に、動物キャラクタクラスを実装します.
 public class Animal : IAnimal
    {
        public IActor Actor { get; set; }

        #region IAnimal   

        public void Move()
        {
            Console.WriteLine("{0} move...",Actor.Name);
        }

        public int Eat(string food)
        {
            Console.WriteLine("{0} eat.{1}.", Actor.Name, food);
            return 1;
        }

        #endregion
    }

実際のロールオブジェクトでは、ここのActorNameなどの「アクセス者」にアクセスできるメソッドです.
次に、Actorビジタークラスの実装に重点を置きます.
class Actor:IActor
    {
        private List<IRole> roles = new List<IRole>();

        public string Name { get; private set; }

        public Actor(string name)
        {
            this.Name = name;
        }

        public void AddRole(IRole role)
        {
            roles.Add(role);
            role.Actor = this;
        }

        public TResule ActAs<T, TResule>(Expression<Func<T, TResule>> exp) where T : class
        {
            //         
            var lambda = exp.Compile();
            TResule result = lambda.Invoke(GetObject<T>());
            //         
            return result;
        }

        public T GetObject<T>() where T : class
        {
            foreach (IRole role in roles)
            {
                if (role is T)
                    return role as T;
            }
            return null;
        }
    }

ActAsメソッドを重点的に見てみましょう.それは自分を指定したロールに変換し、ロールを呼び出す方法ですが、パラメータはExpression.これにより、非常に友好的な方法で符号化することができます.それとも、このコードを呼び出す方法を見てみましょう.
           Actor man = new Actor("zhagnsan");
            man.AddRole(new Animal());//            

            var result=man.ActAs<IAnimal, int>(a => a.Eat("rice"));

            Console.WriteLine("result:{0}",result);

私たちは方法の中で、よく知っている方法で、動物の役の食べ物の方法を呼び出しました.
プログラム出力:
zhagnsan eat.rice.
result:1

冒頭の方法と比較すると、ここでman.ActAsは、zhangsanがロールオブジェクトのインスタンスを持つ機会を外部に知らせることなく、ロールオブジェクトの方法を直接実行し、訪問者が自分のロールに対してより良い「パッケージ」を完了します.つまり、自分だけが自分のキャラクターを実行できる方法が、リアルなシーンに合ったデザインです.
--------境目------------------
PDF.NETオープンソース技術チームに参加して、最も軽くて最も速いフレームワークをすることを歓迎します!