C# 如何允许在每次不重新编译的情况下更改方法的调用方式?

C# 如何允许在每次不重新编译的情况下更改方法的调用方式?,c#,.net,C#,.net,注意:如果这个问题可能不是最清楚的,请提前道歉,但是我正在努力完成一些事情,但是没有必要的知识来充分表达我的想法。我在这里发帖是希望学习更先进的方法来实现我的想法 我有多个对象遵循这样的界面 interface IObj{ void Parse(string document) string Read(string locationId) void Write(string locationId, string valuetoWrite) } void Processor(

注意:如果这个问题可能不是最清楚的,请提前道歉,但是我正在努力完成一些事情,但是没有必要的知识来充分表达我的想法。我在这里发帖是希望学习更先进的方法来实现我的想法

我有多个对象遵循这样的界面

interface IObj{

 void Parse(string document)    

 string Read(string locationId)
 void Write(string locationId, string valuetoWrite)

}
void Processor(){

   Read();
   Read();
   Write();

}
这些对象都表示文本文档结构。一些可以是CSV格式,另一个对象可以是XML,等等

 ObjectA : IObj{ 
 //for example lets say this object represent comma separated values record

 List<string> fields; //list of columns and their values

 void Parse(string input){ //takes the document as string and creates the object representation
     fields.AddRange(input.Split(',');
 }

 Dictionary<string,ObjAlocation> locations;  //maps the locations to an ID

 public string Read(string id){
    //objectA implementation of read
    //knows how to read from ObjALocation only - it takes the correct location that is stored in the dictionary by id and parses it

        string result = string.Empty;

        if (locations.ContainsKey(id))
        {
            ObjALocation position = locations[id];
            if (position.Field <= fields.Count-1)
                result = fields[position.Field];
        }

        return result;
 }

 public void write(string locationId, string valuetoWrite){
    //objectA implementation of write
    //knows how to write to ObjALocationOnly
 }
}



class ObjALocation{  //definition of a location for ObjectA

    public int Field;

}
但是,通常您必须在编译应用程序之前预定义指令。因此,方法及其顺序在Processor()方法中是固定的。但是我不想硬编码指令来调用读写方法。我想让最终用户能够以他们想要的任何顺序和组合调用这些方法。(通过修改XML配置或使用GUI)

这样我就不必每次需要更改指令时都重新编译程序

编辑:有没有一种方法可以使用诸如Func、Action或dynamic之类的c#关键字来完成编辑。我试图避免使用动态代码编译选项

对我来说,有两个问题是同时存在的,
如何像上面那样将读写实例放入Processor()方法中以及如何在每次调用Processor()时以动态方式将它们放入Processor()方法-因为明天Processor()可能会处理一个完全不同的对象,具有不同的read()和write()配置。

您正在寻找一个名为

您可以通过调用对象的
GetType()
方法来获取对象类型的运行时信息。然后,您可以通过调用或从
类型中获取特定方法。一旦获得了要调用的方法的名称,就可以使用其方法调用它。
Invoke
的第一个参数是调用方法的对象,第二个参数是传递给方法的参数数组

明智的做法是,在调用方法之前,使用标记从配置文件中可以执行的方法,并检查属性是否存在,以防止代码执行任意方法。

获取输入

<Root>  
    <Processor Name="ReadValue" Type="ObjectB">
        <Read resultid="1" locationid="12"></Read>
        <Read resultid="2" locationid="34"></Read>
        <Write resultid="3" locationid="4">
            string to write
        </Write>
    </Processor>
    <Processor Name="ReadValue" Type="ObjectA">
        <Read resultid="1" locationid="12"></Read>
        <Read resultid="2" locationid="34"></Read>
        <Write resultid="3" locationid="4">
            string to write
        </Write>
    </Processor>
</Root>

你不应该仅仅因为问题已经结束就删除并重新提问:@Servy为什么不要求澄清而不是这么快结束?@Servy我不明白问题有什么不清楚的地方关闭一个不清楚的问题可以让它得到改进和澄清,而不会因为不清楚而给它带来低质量的答案。这不是适当的做法是不断地重复发布。我不认为他是在寻求反思。基本上,他的xml只包含他已经实现的方法的顺序和参数。感谢你的建议,并指出如何使用属性来防止不必要的方法调用谢谢,它给了我一些可以尝试的东西。我可能会将XML的反序列化与处理分开。也就是说,我可能不会在反序列化为对象并在处理器中使用的每个xml元素上调用processor。@erotavlas当然,您肯定应该将这些步骤分开。我刚才给了你一个简单的例子。
void Processor(){

   Read();
   Read();
   Write();

}
<Root>  
    <Processor Name="ReadValue" Type="ObjectB">
        <Read resultid="1" locationid="12"></Read>
        <Read resultid="2" locationid="34"></Read>
        <Write resultid="3" locationid="4">
            string to write
        </Write>
    </Processor>
    <Processor Name="ReadValue" Type="ObjectA">
        <Read resultid="1" locationid="12"></Read>
        <Read resultid="2" locationid="34"></Read>
        <Write resultid="3" locationid="4">
            string to write
        </Write>
    </Processor>
</Root>
void Main()
{
    var xDoc = XDocument.Load(@"C:\PathToXml\instructions.xml");

    foreach (var processor in xDoc.Root.Elements())
    {
        if (processor.Attribute("Name").Value == "ReadValue")
        {
            var readValueProcessor = new ReadValueProcessor();
            readValueProcessor.Execute(processor);
        }
    }
}

interface IObj
{
    string Read(int resultid, int locationid);
    void Write(int resultid, int locationid, string text);
}

class ObjectA : IObj
{
    public string Read(int resultid, int locationid)
    {
        return resultid + " " + locationid + " From A";
    }

    public void Write(int resultid, int locationid, string text)
    {
        Console.WriteLine(resultid + " " + locationid + " From A : " + text);
    }
}

class ObjectB : IObj
{
    public string Read(int resultid, int locationid)
    {
        return resultid + " " + locationid + " From B";
    }

    public void Write(int resultid, int locationid, string text)
    {
        Console.WriteLine(resultid + " " + locationid + " From B : " + text);
    }
}

class ReadValueProcessor
{
    public void Execute(XElement processorNode)
    {
        var typeAttribute = processorNode.Attribute("Type").Value;
        IObj objectToExecute = null;

        if (typeAttribute == "ObjectA")
        {
            objectToExecute = new ObjectA();
        }
        else if (typeAttribute == "ObjectB")
        {
            objectToExecute = new ObjectB();
        }

        foreach (var action in processorNode.Elements())
        {
            if (action.Name == "Read")
            {
                var resultid = int.Parse(action.Attribute("resultid").Value);
                var locationid = int.Parse(action.Attribute("locationid").Value);
                var result = objectToExecute.Read(resultid, locationid);
                Console.WriteLine(result);
            }
            else if (action.Name == "Write")
            {
                var resultid = int.Parse(action.Attribute("resultid").Value);
                var locationid = int.Parse(action.Attribute("locationid").Value);
                var text = action.Value;
                objectToExecute.Write(resultid, locationid, text);
            }
        }
    }
}