Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “的顺序问题”;“注册”;消息传递场景中.NET类的数量_C#_Class_Static_Constructor_Registration - Fatal编程技术网

C# “的顺序问题”;“注册”;消息传递场景中.NET类的数量

C# “的顺序问题”;“注册”;消息传递场景中.NET类的数量,c#,class,static,constructor,registration,C#,Class,Static,Constructor,Registration,我看到这个问题经常出现,但从来没有得到充分的处理,而且我还没有在堆栈溢出上看到它,所以现在开始。我希望有一种方法可以简明扼要地表达这一点而不缺乏清晰度,但我似乎不能缩短它,所以请容忍我 下面是一个很好的案例研究(当然是我目前的案例)来说明这个问题: 我为许多位置、一个父比较(parentco)和几个卫星位置(centers)编写代码。我有两个“经理”,一个是为家长公司设计的,另一个是为中心设计的(部署了很多次)。我还有两个库,一个用于中心,一个通用库(用于中心和parentco),程序可以包括这

我看到这个问题经常出现,但从来没有得到充分的处理,而且我还没有在堆栈溢出上看到它,所以现在开始。我希望有一种方法可以简明扼要地表达这一点而不缺乏清晰度,但我似乎不能缩短它,所以请容忍我

下面是一个很好的案例研究(当然是我目前的案例)来说明这个问题:

我为许多位置、一个父比较(parentco)和几个卫星位置(centers)编写代码。我有两个“经理”,一个是为家长公司设计的,另一个是为中心设计的(部署了很多次)。我还有两个库,一个用于中心,一个通用库(用于中心和parentco),程序可以包括这两个库,以便与相应的管理员通信(通过TCP)。中心库中有几个类设计用于包装数据库表和其他“消息”以完成其他任务,而通用库中也有一些“消息”,如“结束连接”、“调用进程”等

问题:

当管理器接收到在“通用”库中定义的消息时,它如何知道它是哪种类型的消息?第一个解决方案是这样的:

namespace generic_library
{
    public interface IMessage_Creator
    {
        public IMessage Create_Message(short id);
    }
    public interface IMessage
    {
        short Message_ID { get; }
    }
    /// <summary>Perhaps a message to kill the current connection</summary>
    public class Generic_Message1 : IMessage
    {
        public short Message_ID { get { return ID; } }
        internal const short ID = 1;
    }
    public static class Message_Handler
    {
        private static readonly System.Collections.Generic.List<IMessage_Creator> _creators = 
            new System.Collections.Generic.List<IMessage_Creator>();
        public static void Add_Creator(IMessage_Creator creator)
        {
            _creators.Add(creator);
        }
        public static IMessage Get_Message(short id)
        {
            switch (id)
            {//the Generic library knows about the generic messages...
                case Generic_Message1.ID:
                    return new Generic_Message1();
            }
            //no generic message found, search the registered creators.
            IMessage ret = null;
            foreach (IMessage_Creator creator in _creators)
            {
                ret = creator.Create_Message(id);
                if (ret != null)
                {
                    return ret;
                }
            }
            //null if no creator was found.
            return ret;
        }
    }
}
namespace center
{
    public class Center_Creator : generic_library.IMessage_Creator
    {
        static Center_Creator()
        {
            generic_library.Message_Handler.Add_Creator(new Center_Creator());
        }
        public generic_library.IMessage Create_Message(short id)
        {
            switch (id)
            {//The center library knows about center-specific messages
                case center_message1.ID:
                    return new center_message1();
            }
            //we return null to say, "I don't know about that message id."
            return null;
        }
    }
    public class center_message1 : generic_library.IMessage
    {
        public short Message_ID
        {
            get { return ID; }
        }
        internal const short ID = 2;
    }
}
命名空间通用库
{
公共接口IMessage_创建者
{
公共IMessage创建_消息(短id);
}
公共接口IMessage
{
短消息_ID{get;}
}
///可能是要终止当前连接的消息
公共类通用消息1:IMessage
{
公共短消息{u ID{get{return ID;}}
内部常量短ID=1;
}
公共静态类消息\u处理程序
{
私有静态只读System.Collections.Generic.List\u创建者=
新建System.Collections.Generic.List();
公共静态无效添加创建者(IMessage创建者)
{
_creators.Add(creator);
}
公共静态IMessage Get_消息(短id)
{
开关(id)
{//泛型库知道有关泛型消息的信息。。。
案例通用消息1.ID:
返回新的泛型消息1();
}
//未找到一般消息,请搜索已注册的创建者。
IMessage ret=null;
foreach(IMessage_Creator in_creators)
{
ret=创建者。创建消息(id);
如果(ret!=null)
{
返回ret;
}
}
//如果未找到创建者,则为null。
返回ret;
}
}
}
名称空间中心
{
公共类中心_创建者:generic_library.IMessage_创建者
{
静态中心创建器()
{
generic_library.Message_Handler.Add_Creator(new Center_Creator());
}
公共通用_library.IMessage创建_消息(短id)
{
开关(id)
{//中心库知道中心特定的消息
案例中心消息1.ID:
返回新的中心消息1();
}
//我们返回null表示,“我不知道该消息id。”
返回null;
}
}
公共类中心_消息1:generic_library.IMessage
{
公共短消息\u ID
{
获取{return ID;}
}
内部常量短ID=2;
}
}
一点解释。如您所见,中心和通用库都有自己的消息可以处理。中心接口(此处由
名称空间中心
表示)在静态构造函数中注册其创建者
中心创建者
,因此当
消息处理程序
获取其类型的消息时,将调用创建者生成正确的消息

这种方法的问题:

您可能已经看到了这里的问题,即:

如果代码从未访问过类中心创建者(从未创建过一个,也从未调用过静态方法),则在收到该类型的消息之前,应该是这样,静态构造函数,
static Center\u Creator()
,因此
message\u Handler
永远不知道该创建者

这一切都很好,但我不知道如何修复它。许多人建议使用反射来调用
Center\u Creator
类型初始值设定项
,但我不想让每个使用此库的程序都承担这个负担

堆栈溢出社区的建议是什么?请让我知道我是否可以简化此过程,以帮助社区更容易访问

编辑: 代码用于通用库和中心库。如您所见,我在母公司库中也会遇到同样的问题

.

让我们来详细分析一下:

  • 您有一个用于发送和接收特定类型消息的应用程序
  • 但是,必须先注册消息类型,然后才能读取它
  • 在发送消息之前,您不会注册该类型,但是
  • 您希望在编写消息之前能够阅读消息
显然,答案是您在错误的时间注册了消息类型

我建议为消息类型显式调用
Init()
方法。这可以通过使用反射扫描库来查看是否定义了类型,或者手动列出它们来实现。

一些想法:

  • 使用.NET序列化来序列化/反序列化消息,并将它们放入两端使用的类库中(甚至使用WCF来处理通信)
  • 在第一次调用Get_消息(“if(!initialized)FindAddCreators()”)时,向creator类添加自定义属性,并使用反射填充creator列表;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace SO
    {
        class Program
        {
            static void Main(string[] args)
            {
                MessageFactory factory = new MessageFactory();
    
                IMessage msg = factory.CreateObject(1);
                IMessage msg2 = factory.CreateObject(2);
            }
        }
    
        public interface IMessage
        {
            short Message_ID { get; }
        } 
    
        public class Generic_Message1 : IMessage 
        { 
            public short Message_ID { get { return ID; } } 
            internal const short ID = 1; 
        } 
    
        public class center_message1 : IMessage 
        { 
            public short Message_ID { get { return ID; } } 
            internal const short ID = 2; 
        } 
    
        public class MessageFactory
        {
            private Dictionary<short, Type> messageMap = new Dictionary<short, Type>();
    
            public MessageFactory()
            {
                Type[] messageTypes = Assembly.GetAssembly(typeof(IMessage)).GetTypes();
                foreach (Type messageType in messageTypes)
                {
                    if (!typeof(IMessage).IsAssignableFrom(messageType) || messageType == typeof(IMessage))
                    {
                        // messageType is not derived from IMessage   
                        continue;
                    }
    
                    IMessage message = (IMessage)Activator.CreateInstance(messageType);               
                    messageMap.Add(message.Message_ID, messageType);
                }
            }
    
            public IMessage CreateObject(short Message_ID, params object[] args)
            {
                return (IMessage)Activator.CreateInstance(messageMap[Message_ID], args);
            }
        } 
    
    }
    
    // Read customMessageDllName and customMessageClassName from your config file 
    Assembly assembly = Assembly.Load(customMessageDllName); 
    IMessage customMessage = (IMessage)assembly.CreateInstance(customMessageClassName); 
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    
    namespace Playground
    {
        public class Program
        {
            static void Main(string[] args)
            {
                PluginHost host = new PluginHost();
                host.PrintListOfPlugins();
                Console.ReadKey();
            }
        }
    
        public class PluginHost
        {
            [ImportMany]
            public IEnumerable<IPlugin> Plugins { get; set; }
    
            public PluginHost()
            {
                var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
                var container = new CompositionContainer(catalog);
                container.ComposeParts(this);
            }
    
            public void PrintListOfPlugins()
            {
                foreach (IPlugin plugin in Plugins)
                    Console.WriteLine(plugin.Description);
            }
        }
    
        public interface IPlugin
        {
            string Description { get; }
        }
    
        [Export(typeof(IPlugin))]
        public class ExamplePlugin : IPlugin
        {
            #region IPlugin Members
    
            public string Description
            {
                get { return "I'm an example plugin!"; }
            }
    
            #endregion
        }
    }
    
    Generic_lib.IMessage msg = Generic_lib.Message_Handler.get_message(2); //a Center Message
    if (msg is Center_lib.Center_Message)
    {
        System.Console.WriteLine("got center message");
    }
    
    static Message_Handler()
    {
        //here, do the registration.
        int registered = 0;
        System.Reflection.Assembly[] assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
        foreach (System.Reflection.Assembly asm in assemblies)
        {
            System.Type[] types = asm.GetTypes();
            foreach (System.Type t in types)
            {
                System.Type[] interfaces = t.GetInterfaces();
                foreach (System.Type i in interfaces)
                {
                    if (i == typeof(IMessage_Creator))
                    {
                        System.Reflection.ConstructorInfo[] constructors = t.GetConstructors();
                        foreach (System.Reflection.ConstructorInfo ctor in constructors)
                        {
                            if (ctor.GetParameters().Length == 0)
                            {
                                Add_Creator(ctor.Invoke(new object[0]) as IMessage_Creator);
                                registered++;
                            }
                        }
                    }
                }
            }
        }
        System.Diagnostics.Debug.WriteLine("registered " + registered.ToString() + " message creators.");
    }
    
    if (msg is Center_lib.Center_Message) ;