【问题标题】:Using COM works with VBScript but fails with c#.net使用 COM 与 VBScript 一起工作,但在 c#.net 中失败
【发布时间】:2012-05-29 13:46:50
【问题描述】:

我在本地系统上注册了一个 DLL。 (我不拥有)

当我使用 VBScript 创建 COM 对象并调用该函数时,一切正常:

set Elo = CreateObject("jniwrapper.elocomserver")
Elo.refreshIntray()

但是当使用 C#.net 时,我得到一个 NotImplementedException:

Type javaClientComServerType = Type.GetTypeFromProgID("jniwrapper.elocomserver");
dynamic eloJavaClient = Activator.CreateInstance(javaClientComServerType);

eloJavaClient.refreshIntray();

知道这里发生了什么以及如何解决它吗?

【问题讨论】:

    标签: c# .net vbscript com-interop notimplementedexception


    【解决方案1】:

    这似乎是一个与 .NET COM 互操作通过 DLR(动态语言运行时)与 COM-Server(通过 JNI 包装的 Java 程序使用)的 COM 桥相关联的问题。我怀疑后者是来自 Teamdev 的 ComfyJ。您可以通过提供 IDynamicMetaObjectProvider 和 DynamicMetaObject 的实现来解决此问题。首先看下面的代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Dynamic;
    using System.IO;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    using System.Diagnostics;
    
    class DynamicCOMObject : IDynamicMetaObjectProvider, IDisposable 
    {
        private Type m_comType = null;
        private object m_comHolder = null;
    
        public DynamicCOMObject(string progId)
        {        
            m_comType = Type.GetTypeFromProgID(progId);
            m_comHolder = Activator.CreateInstance(m_comType);
        }
    
        public void Dispose()
        {
            if (m_comHolder != null)
            {
                Marshal.ReleaseComObject(m_comHolder);
                m_comHolder = null;
            }
        }
    
        #region IDynamicMetaObjectProvider Members
        DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(
            System.Linq.Expressions.Expression parameter)
        {
            return new DynamicCOMObjectMetaObject(parameter, this);
        }
        #endregion
    
        private class DynamicCOMObjectMetaObject : DynamicMetaObject
        {
            internal DynamicCOMObjectMetaObject(
                System.Linq.Expressions.Expression parameter,
                DynamicCOMObject value)
                : base(parameter, BindingRestrictions.Empty, value)
            {
            }
    
            public override DynamicMetaObject BindSetMember(SetMemberBinder binder,
                DynamicMetaObject value)
            {
                // Method to call in the containing class:
                string methodName = "SetValue";
    
                // setup the binding restrictions.
                BindingRestrictions restrictions =
                    BindingRestrictions.GetTypeRestriction(Expression, LimitType);
    
                // setup the parameters:
                Expression[] args = new Expression[2];
                // First parameter is the name of the property to Set
                args[0] = Expression.Constant(binder.Name);
                // Second parameter is the value
                args[1] = Expression.Convert(value.Expression, typeof(object));
    
                // Setup the 'this' reference
                Expression self = Expression.Convert(Expression, LimitType);
    
                // Setup the method call expression
                Expression methodCall = Expression.Call(self,
                        typeof(DynamicCOMObject).GetMethod(methodName),
                        args);
    
                // Create a meta object to invoke Set later:
                DynamicMetaObject setDictionaryEntry = new DynamicMetaObject(
                    methodCall,
                    restrictions);
                // return that dynamic object
                return setDictionaryEntry;
            }
    
            public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
            {
                // Method call in the containing class:
                string methodName = "GetValue";
    
                // One parameter
                Expression[] parameters = new Expression[]
                {                
                    Expression.Constant(binder.Name)
                };
    
                DynamicMetaObject getDictionaryEntry = new DynamicMetaObject(
                    Expression.Call(
                        Expression.Convert(Expression, LimitType),
                        typeof(DynamicCOMObject).GetMethod(methodName),
                        parameters),
                    BindingRestrictions.GetTypeRestriction(Expression, LimitType));
                return getDictionaryEntry;
            }
    
            public override DynamicMetaObject BindInvokeMember(
                InvokeMemberBinder binder, DynamicMetaObject[] args)
            {
                Expression[] parameters = new Expression[2];
                Expression[] subs = new Expression[args.Length];
    
                parameters[0] = Expression.Constant(binder.Name);
    
                for (int i = 0; i < args.Length; i++)
                    subs[i] = args[i].Expression;
    
                parameters[1] = Expression.NewArrayInit(typeof(object), subs);
    
                DynamicMetaObject methodInfo = new DynamicMetaObject(
                    Expression.Call(
                    Expression.Convert(Expression, LimitType),
                    typeof(DynamicCOMObject).GetMethod("CallMethod"),
                    parameters),
                    BindingRestrictions.GetTypeRestriction(Expression, LimitType));
                return methodInfo;
            }
        }
    
        public object SetValue(string key, object value)
        {
            return m_comType.InvokeMember(key,
                BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public,
                null,
                m_comHolder,
                new object[] { value });   
        }
    
        public object GetValue(string key)
        {
            return m_comType.InvokeMember(key,
                BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.Public,
                null,
                m_comHolder,
                null);          
        }
    
        public object CallMethod(string methodName, params object[] parameters)
        {
            return m_comType.InvokeMember(methodName,
                BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
                null,
                m_comHolder,
                parameters);        
        }
    }
    

    用法:

            using (dynamic client = new DynamicCOMObject("jniwrapper.elocomserver"))
            {                
                client.refreshIntray();
            }
    

    【讨论】:

    【解决方案2】:

    仅用于文档;有一条捷径:

    class EloComServer : DynamicObject, IDisposable
    {
        private Type javaClientType;
        private object elo;
    
        public EloComServer()
        {
            javaClientType = Type.GetTypeFromProgID("jniwrapper.elocomserver");
            elo = Activator.CreateInstance(javaClientType);
        }
    
        ~EloComServer()
        {
            this.Dispose();
        }
    
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            try
            {
                result = javaClientType.InvokeMember(binder.Name,
                        BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
                        null, elo, args);
    
                return true;
            }
            catch
            {
                result = null;
                return false;
            }
        }
    
        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            try
            {
                javaClientType.InvokeMember(binder.Name,
                        BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance,
                        null, elo, new object[] { value });
    
                return true;
            }
            catch
            {
                return false;
            }
        }
    
        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            try
            {
                result = javaClientType.InvokeMember(binder.Name,
                        BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance,
                        null, elo, new object[0]);
    
                return true;
            }
            catch
            {
                result = null;
                return false;
            }
        }
    
        #region IDisposable Members
    
        public void Dispose()
        {
            if (this.elo != null)
            {
                Marshal.ReleaseComObject(elo); 
            }
        }
    
        #endregion
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-03
      • 2021-05-17
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 2017-09-02
      • 2013-03-26
      • 1970-01-01
      • 2016-07-22
      相关资源
      最近更新 更多