Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.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# 如何为C创建插件#_C#_Mef - Fatal编程技术网

C# 如何为C创建插件#

C# 如何为C创建插件#,c#,mef,C#,Mef,每个人都说使用MEF。就这样。现在就我的生活而言,我不知道如何使用它 我下载了一个示例项目: public interface ICalculator { String Calculate(String input); } public interface IOperation { int Operate(int left, int right); } public interface IOperationDat

每个人都说使用MEF。就这样。现在就我的生活而言,我不知道如何使用它

我下载了一个示例项目:

public interface ICalculator
    {
        String Calculate(String input);
    }

    public interface IOperation
    {
        int Operate(int left, int right);
    }

    public interface IOperationData
    {
        Char Symbol { get; }
    }

    [Export(typeof(IOperation))]
    [ExportMetadata("Symbol", '+')]
    class Add : IOperation
    {
        public int Operate(int left, int right)
        {
            return left + right;
        }
    }

    [Export(typeof(IOperation))]
    [ExportMetadata("Symbol", '-')]
    class Subtract : IOperation
    {

        public int Operate(int left, int right)
        {
            return left - right;
        }

    }



    [Export(typeof(ICalculator))]
    class MySimpleCalculator : ICalculator
    {
        [ImportMany]
        IEnumerable<Lazy<IOperation, IOperationData>> operations;

        public String Calculate(String input)
        {
            int left;
            int right;
            Char operation;
            int fn = FindFirstNonDigit(input); //finds the operator
            if (fn < 0) return "Could not parse command.";

            try
            {
                //separate out the operands
                left = int.Parse(input.Substring(0, fn));
                right = int.Parse(input.Substring(fn + 1));
            }
            catch
            {
                return "Could not parse command.";
            }

            operation = input[fn];

            foreach (Lazy<IOperation, IOperationData> i in operations)
            {
                if (i.Metadata.Symbol.Equals(operation)) return i.Value.Operate(left, right).ToString();
            }
            return "Operation Not Found!";
        }

        private int FindFirstNonDigit(String s)
        {

            for (int i = 0; i < s.Length; i++)
            {
                if (!(Char.IsDigit(s[i]))) return i;
            }
            return -1;
        }


    }


    class Program
    {
        private CompositionContainer _container;

        [Import(typeof(ICalculator))]
        public ICalculator calculator;


        private Program()
        {
            //An aggregate catalog that combines multiple catalogs
            var catalog = new AggregateCatalog();
            //Adds all the parts found in the same assembly as the Program class
            catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
            catalog.Catalogs.Add(new DirectoryCatalog(@"C:\Users\Lee Yi\Desktop\Everything, for the moment\Coding\Simple Calculator MEF Application\C#\SimpleCalculator3\Extensions"));


            //Create the CompositionContainer with the parts in the catalog
            _container = new CompositionContainer(catalog);

            //Fill the imports of this object
            try
            {
                this._container.ComposeParts(this);
            }
            catch (CompositionException compositionException)
            {
                Console.WriteLine(compositionException.ToString());
            }
        }


        static void Main(string[] args)
        {
            Program p = new Program(); //Composition is performed in the constructor
            String s;
            Console.WriteLine("Enter Command:");
            while (true)
            {
                s = Console.ReadLine();
                Console.WriteLine(p.calculator.Calculate(s));
            }


        }
    }
例如,到另一个.dll

在我的例子中,我正在System.Windows.Forms.Button类中使用此功能,其中我有如下内容:

class SpeakButton : Button
{ 
    public SpeakButton()
    { //Constructor that adds the speech handler automatically
        this.Click += new EventHandler(Speak_Button);
    }

    private void Speak_Button(object sender, EventArgs e)
    {
        Speaking.Speak((sender as Button).Text);
    }
}
但是我想让
Speaking.Speak()
函数(它实际上调用SpeechSynthesizer的SpeakAsync函数)是可选的,并且可以作为单独的.dll文件安装

有人能解释一下我是怎么做的吗

口语课的定义如下:

class Speaking
{
    //Private fields (Hiding implementation code)
    private static SpeechSynthesizer Speaker = new SpeechSynthesizer();
    private static State state = State.Disabled;

    //Public properties
    public static int Volume
    {
        get { return Speaker.Volume; }
        set { Speaker.Volume = value; }
    }

    public static int Rate
    {
        get { return Speaker.Rate; }
        set { Speaker.Rate = value; }
    }

    public static State Speech
    {
        get { return state; }
        set { state = value; }
    }

    public static VoiceGender Gender
    {
        get { return Speaker.Voice.Gender; }
        set { Speaker.SelectVoiceByHints(value); }
    }

    public enum State { Enabled = 1, Disabled = 0 };

    public static void Speak(object message)
    { //Say stuff
        if (state == State.Disabled) { return; }
        Speaker.SpeakAsync(message.ToString());
    }

    public static void Cancel() { Speaker.SpeakAsyncCancelAll(); }
}

MEF不能与静态类一起正常工作,所以我不能评论您的特定用例。如果要将代码迁移到插件体系结构的另一个DLL,您将有三个不同的程序集:主EXE、包含插件接口的程序集和插件程序集。主EXE和插件程序集引用插件接口程序集。例如:

Main EXE

  static class Program
  {
    static void Main()
    {
      Controller win = new Controller();
      win.ListPlugins();
    }
  }

  public class Controller
  {
    [System.ComponentModel.Composition.ImportMany]
    IEnumerable<Lazy<Interface.IPlugin>> plugins;

    System.ComponentModel.Composition.Hosting.CompositionContainer compContainer;

    public Controller()
    {
      var catalog = GetMefCatalogs();
      this.compContainer = new System.ComponentModel.Composition.Hosting.CompositionContainer(catalog);

      try
      {
        System.ComponentModel.Composition.AttributedModelServices.ComposeParts(this.compContainer, this);
      }
      catch (System.Reflection.ReflectionTypeLoadException ex)
      {
        foreach (Exception inner in ex.LoaderExceptions)
        {
          Console.WriteLine("Reflection error: {0}", inner.Message);
        }
      }
      catch (System.ComponentModel.Composition.CompositionException ex)
      {
        Console.WriteLine(ex.ToString());
      }

    }

    public void ListPlugins()
    {
      foreach (var pv in this.plugins)
      {
        Console.WriteLine(pv.Value.Name);
      }
    }

    public static System.ComponentModel.Composition.Hosting.AggregateCatalog GetMefCatalogs()
    {
      var catalog = new System.ComponentModel.Composition.Hosting.AggregateCatalog();
      // You should probably use these two lines, or the following lines, but not both.  If you use
      // this option you will need to ensure that the libs are all in the same directory.
      catalog.Catalogs.Add(new System.ComponentModel.Composition.Hosting.DirectoryCatalog(System.IO.Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory), "*.dll"));
      catalog.Catalogs.Add(new System.ComponentModel.Composition.Hosting.DirectoryCatalog(System.IO.Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory), "*.exe"));
      //foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
      //{
      //  if (!assembly.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase) &&
      //    !assembly.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase) &&
      //    !assembly.FullName.StartsWith("mscorlib", StringComparison.OrdinalIgnoreCase) &&
      //    !assembly.FullName.StartsWith("Accessibility", StringComparison.OrdinalIgnoreCase) &&
      //    !assembly.FullName.StartsWith("vshost32", StringComparison.OrdinalIgnoreCase))
      //  {
      //    Console.WriteLine("Found assembly: " + assembly.FullName);
      //    catalog.Catalogs.Add(new System.ComponentModel.Composition.Hosting.AssemblyCatalog(assembly));
      //  }
      //}
      return catalog;
    }
  }
插件程序集

  public interface IPlugin
  {
    string Name { get; }
    double GetRandom();
  }
  [System.ComponentModel.Composition.Export(typeof(Interface.IPlugin))]
  public class Plugin : Interface.IPlugin
  {
    private Random random;
    public Plugin()
    {
      this.random = new Random(DateTime.Now.Ticks.GetHashCode());
    }

    public string Name
    {
      get { return "Plugin"; }
    }

    public double GetRandom()
    {
      return this.random.NextDouble() * 10;
    }
  }

当然,为了使用MEF,您需要在插件和主EXE程序集(但不是插件程序集)中添加对System.ComponentModel.Composition的引用。

MEF对我来说总是很难理解,我非常喜欢Mono.Addins。MEF很好,但对于90%的插件项目来说似乎有些过头了。
  [System.ComponentModel.Composition.Export(typeof(Interface.IPlugin))]
  public class Plugin : Interface.IPlugin
  {
    private Random random;
    public Plugin()
    {
      this.random = new Random(DateTime.Now.Ticks.GetHashCode());
    }

    public string Name
    {
      get { return "Plugin"; }
    }

    public double GetRandom()
    {
      return this.random.NextDouble() * 10;
    }
  }