C#COM和附加事件 [英] C# COM and attaching events

查看:136
本文介绍了C#COM和附加事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有这个传统类型的应用程序我试图理解和维护,需要一些帮助。
我还没有太多涉足到远程但这种方法似乎是使用第三方COM组件。



该文档是合理的,但没有谈及太多。NET以及如何连接事件处理程序。 。相反,它记录(并在溶液中时)有关如何创建经由Activator.CreateInstance该对象的一个​​实例



所以目前它是这样做的:

  mainObj = Activator.CreateInstance(Type.GetTypeFromProgID(xxxRemote.clsxxxJob)); 

这很好。



但我要附加一个事件处理程序以侦听由激活创建的实例化对象的特定事件。



的文档给我曝光的事件,但是,如何去使用这种方法时,它们连接起来没有例子。



人对如何使用COM这样?


解决方案<时要连接事件的任何想法/ DIV>

应该是通过正常的反映。



有在MSDN指导像的 http://msdn.microsoft.com/en-us/library/ms228976(v = vs.110)的.aspx



的问题是,定义将被挂在事件的方法,你不会有定义的类型,将不得不做一些IL emmiting黑魔法打造运行的方法。这是一个有趣的问题。



我要送的正常的方式打开通过COM ADO连接的例子(只是为了有东西,将调用事件处理程序) 。然后,我这样做,困难的方式的另一个例子。



在代码的混乱很抱歉,但它只是一个样本。

 使用系统; 
使用System.Text;
使用System.Collections.Generic;
使用System.Linq的;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用的System.Reflection;
使用ADODB;
使用System.Reflection.Emit;

命名空间COMTests.Tests
{
[TestClass中]
公共类UnitTest1
{
私人字符串服务器;
私人字符串数据库;
私人字符串用户;
私人字符串密码;

[TestInitialize]
公共无效初始化()
{
this.server =;
this.database =;
this.user =;
this.password =;
}

[TestMethod的]
公共无效TestCreateConectionTheSaneWay()
{
ADODB.Connection连接=新ADODB.Connection();
connection.Provider =SQLOLEDB;
connection.ConnectionString =的String.Format(服务器= {0};数据库= {1};用户ID = {2};密码= {3},
this.server,this.database ,this.user,this.password);
connection.ConnectComplete + =新ADODB.ConnectionEvents_ConnectCompleteEventHandler(TheConnectionComplete);
connection.Open();


}

[TestMethod的]
公共无效TestCreateConnectionTheInsaneWay()
{
型connectionType = Type.GetTypeFromProgID( ADODB.Connection);

EventInfo EVENTTYPE = connectionType.GetEvent(ConnectComplete);

类型[] = argumentTypes
(从eventType.EventHandlerType.GetMethod(调用)信息参数p GetParameters()
选择p.ParameterType).ToArray<类型> ();

MethodInfo的处理程序= FabricateAMethod(argumentTypes,哇,我应该很高兴,因为它的工作原理?,
Ass2,2型,方法2);
代表D2 = Delegate.CreateDelegate(eventType.EventHandlerType,处理,真正的);

对象o = Activator.CreateInstance(connectionType);
eventType.AddEventHandler(邻,D2);

connectionType.GetProperty(提供者)的SetValue(邻,SQLOLEDB,NULL);
connectionType.GetProperty(的ConnectionString)的SetValue(O,的String.Format(服务器= {0};数据库= {1};用户ID = {2};密码= {3},
this.server,this.database,this.user,this.password),NULL);
connectionType.GetMethod(打开)调用(邻,新的对象[] {,,,-1})。

}

[TestMethod的]
公共无效TestFabricatedMethod()
{
MethodInfo的M = FabricateAMethod(新类型[] {}, 。叶氏工程,ASS1,类型1,方法一);
m.Invoke(空,新的对象[] {});
}

私人的MethodInfo FabricateAMethod(键入[]参数,字符串stringToPrint,字符串的AssemblyName,
字符串的typeName,字符串methodName中)
{
的AssemblyName aName =新的AssemblyName(的AssemblyName);
AssemblyBuilder AB =
AppDomain.CurrentDomain.DefineDynamicAssembly(
aName,
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder MB =
ab.DefineDynamicModule(aName.Name,aName.Name +.DLL);

TypeBuilder TB = mb.DefineType(
的typeName,
TypeAttributes.Public);

MethodBuilder方法= tb.DefineMethod(方法名,MethodAttributes.Public | MethodAttributes.Static,
的typeof(无效),参数);

MethodInfo的writeString = typeof运算(控制台).GetMethod(的WriteLine,
新型[] {typeof运算(字符串)});
的ILGenerator IL = method.GetILGenerator();

il.Emit(OpCodes.Ldstr,stringToPrint);
il.EmitCall(OpCodes.Call,writeString,NULL);
il.Emit(OpCodes.Ret);

返回tb.CreateType()实现getMethod(方法名)。
}

公共静态无效TheConnectionComplete(错误PERROR,楼盘EventStatusEnum adStatus,连接pConnection)
{
Console.WriteLine(正常途径。);
}

}



}


So, I have this legacy type app I am trying to understand and maintain and need some help. I have not dabbled much into Remoting but this solution appears to be using 3rd party COM components.

The documentation is reasonable but does not talk much about .NET and how to attach event handlers. Instead it documents (and is used in the solution) about how to create an instance of the object via Activator.CreateInstance.

so currently it is doing this:

mainObj = Activator.CreateInstance(Type.GetTypeFromProgID("xxxRemote.clsxxxJob"));

that's fine.

But I want to attach an event handler to listen to a specific event on that instantiated object created by the Activator.

The documentation gives me the events exposed but no examples on how to go about wiring them up when using this approach.

anyone have any ideas on how to wire up events when using COM like this?

解决方案

it should be through normal reflection.

There's a guide in msdn like http://msdn.microsoft.com/en-us/library/ms228976(v=vs.110).aspx

The problem is that to define the methods that will be hooked to the events, you won't have the types defined and will have to do some IL emmiting black magic to build the methods in runtime. It's an interesting problem.

I'm sending an example of the "normal" way opening an ADO connection through COM (just to have something that will call an event handler). Then, I have another example of doing this, the hard way.

Sorry by the mess in the code, but it is just a sample.

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using ADODB;
using System.Reflection.Emit;

namespace COMTests.Tests
{
[TestClass]
public class UnitTest1
{
    private string server;
    private string database;
    private string user;
    private string password;                

    [TestInitialize]
    public void Initialize()
    {
        this.server = "";
        this.database = "";
        this.user = "";
        this.password = "";
    }

    [TestMethod]
    public void TestCreateConectionTheSaneWay()
    {
        ADODB.Connection connection = new ADODB.Connection();
        connection.Provider = "sqloledb";
        connection.ConnectionString = String.Format("Server={0};Database={1};User Id={2};Password={3}",
            this.server, this.database, this.user, this.password);
        connection.ConnectComplete += new ADODB.ConnectionEvents_ConnectCompleteEventHandler(TheConnectionComplete);
        connection.Open();


    }

    [TestMethod]
    public void TestCreateConnectionTheInsaneWay()
    {            
        Type connectionType = Type.GetTypeFromProgID("ADODB.Connection");

        EventInfo eventType = connectionType.GetEvent("ConnectComplete");            

        Type[] argumentTypes =
            (from ParameterInfo p in eventType.EventHandlerType.GetMethod("Invoke").GetParameters()
             select p.ParameterType).ToArray<Type>();

        MethodInfo handler = FabricateAMethod(argumentTypes, "Wow! Should I be happy because it works?", 
            "Ass2", "Type2", "Method2");            
        Delegate d2 = Delegate.CreateDelegate(eventType.EventHandlerType, handler, true);                       

        object o = Activator.CreateInstance(connectionType);
        eventType.AddEventHandler(o, d2);            

        connectionType.GetProperty("Provider").SetValue(o, "sqloledb", null);
        connectionType.GetProperty("ConnectionString").SetValue(o, String.Format("Server={0};Database={1};User Id={2};Password={3}",
            this.server, this.database, this.user, this.password), null);
        connectionType.GetMethod("Open").Invoke(o, new object[] { "", "", "", -1 });            

    }

    [TestMethod]
    public void TestFabricatedMethod()
    {    
        MethodInfo m = FabricateAMethod(new Type[] {}, "Yeap. Works.", "Ass1", "Type1", "Method1");
        m.Invoke(null, new Object[] { });
    }

    private MethodInfo FabricateAMethod(Type[] arguments, string stringToPrint, string assemblyName, 
        string typeName, string methodName)
    {
        AssemblyName aName = new AssemblyName(assemblyName);
        AssemblyBuilder ab =
            AppDomain.CurrentDomain.DefineDynamicAssembly(
                aName,
                AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder mb =
           ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

        TypeBuilder tb = mb.DefineType(
            typeName,
            TypeAttributes.Public);

        MethodBuilder method = tb.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static,
           typeof(void), arguments);

        MethodInfo writeString = typeof(Console).GetMethod("WriteLine",
        new Type[] { typeof(string) });
        ILGenerator il = method.GetILGenerator();

        il.Emit(OpCodes.Ldstr, stringToPrint);
        il.EmitCall(OpCodes.Call, writeString, null);
        il.Emit(OpCodes.Ret);

        return tb.CreateType().GetMethod(methodName);
    }

    public static void TheConnectionComplete(Error pError, ref EventStatusEnum adStatus, Connection pConnection)
    {
        Console.WriteLine("The normal way.");
    }

}

}

这篇关于C#COM和附加事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆