Произвольная диспетчеризация в .NET
От: m.a.g. Мальта http://dottedmag.net/
Дата: 25.12.02 11:22
Оценка:
Hi.

Намучившись к кодом, подобным

switch(nodeName)
{
case "Node1": handleNode1(node); break;
case "Node2": handleNode2(node); break;
...
case "Node543": handleNode543(node); break;
}


я придумал следующий диспетчер:

using System;
using System.Reflection;
using System.Collections;

namespace utils
{
  public class DuplicateDefaultDispatcherException : ApplicationException
  {
    public DuplicateDefaultDispatcherException() {}
    public DuplicateDefaultDispatcherException(string msg) : base(msg) {}
    public DuplicateDefaultDispatcherException(string msg, Exception inner) : base(msg, inner) {}
  }

  [AttributeUsage(AttributeTargets.Method)]
  public class DispatchByAttribute : Attribute
  {
    public DispatchByAttribute(object a) { _a = a; }

    public object attribute { get { return _a; } }

    private object _a;
  }

  [AttributeUsage(AttributeTargets.Method)]
  public class DefaultDispatcherAttribute : Attribute
  {
  }

  public class CustomDispatcher
  {
    protected CustomDispatcher()
    {
    }

    protected void EnumerateHandlers(Type dt)
    {
      foreach(MemberInfo mi in this.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Public))
        {
          DispatchByAttribute dba = (DispatchByAttribute)Attribute.GetCustomAttribute(mi, typeof(DispatchByAttribute));

          if(dba != null)
          {
            _Handlers.Add(dba.attribute, Delegate.CreateDelegate(dt, this, mi.Name));
            prj2make.MessageLog.Info("mi.name");
          }

          DefaultDispatcherAttribute da = (DefaultDispatcherAttribute)Attribute.GetCustomAttribute(mi, typeof(DefaultDispatcherAttribute));

          if(da != null)
          {
            if(_DefaultHandler != null)
              throw new DuplicateDefaultDispatcherException("Second Default Handler");

            _DefaultHandler = Delegate.CreateDelegate(dt, this, mi.Name);
          }
        }
    }

    protected Delegate GetHandler(object o)
    {
      if(_Handlers.Contains(o))
        return (Delegate)_Handlers[o];

      return _DefaultHandler;
    }

    private SortedList _Handlers = new SortedList();
    private Delegate _DefaultHandler = null;
  }
}


Может, кому пригодится...

Принимать внутрь так:

  public delegate void DelegateType();

  public class StringDispatcherTestImpl : CustomDispatcher
  {
    [DispatchBy("one")]
    public void One()
    {
    }

    [DispatchBy("two")]
    public void Two()
    {
    }

    [DefaultDispatcher()]
    public void Default()
    {
    }

    public StringDispatcherTestImpl()
    {
      EnumerateHandlers(typeof(DelegateType));
    }
  }


После чего получать обработчик посредством
GetHandler(o);
Re: Произвольная диспетчеризация в .NET
От: AndreiM  
Дата: 28.01.03 03:27
Оценка:
Здравствуйте, m.a.g., Вы писали:

MAG>Hi.


MAG>Намучившись к кодом, подобным


MAG>
MAG>switch(nodeName)
MAG>{
MAG>case "Node1": handleNode1(node); break;
MAG>case "Node2": handleNode2(node); break;
MAG>...
MAG>case "Node543": handleNode543(node); break;
MAG>}
MAG>


Обычно это говорит о недостатке проэктирования и в таком случае используется DP Visitor.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.