【问题标题】:Problems with .NET Remoting TransparentProxy.NET Remoting TransparentProxy 的问题
【发布时间】:2012-12-18 08:50:27
【问题描述】:

我正在尝试使用反射在 AppDomain 中执行一些代码。 这是我的代码:

AppDomain appDomain = GetSomehowAppDomain(); 
string typeAssembly = GetTypeAssembly();
string typeName = GetTypeName();
object targetObject = appDomain.CreateInstanceAndUnwrap(typeAssembly, typeName);
MethodInfo methodInfo = targetObject.GetType().GetMethod(methodName);
object result = methodInfo.Invoke(targetObject, methodParams);

当此代码在网站下运行时,一切正常。 但是,当我从调用 WCF 服务的控制台应用程序执行此操作时,它会尝试调用上述代码 - methodInfonull,我在最后一行得到 NullReferenceException

顺便说一句,targetObjectSystem.Runtime.Remoting.Proxies.__TransparentProxy 类型,我假设如果它以 GoF 模式代理,这意味着我可以访问类型的成员,这是用于代理的原始来源。但是targetObject 没有typeName 类型的成员。

使用targetObject.GetType().GetMethods()我发现它有7个方法:

  1. GetLifetimeService
  2. 初始化LifetimeService
  3. CreateObjRef
  4. ToString
  5. 等于
  6. GetHashCode
  7. 获取类型

targetObject 应该是 WorkflowManager 类型的代理。

public class WorkflowsManager : MarshalByRefObject, ISerializable, IDisposable, IWorkflowManager

【问题讨论】:

  • 您的代码中的res 是什么?您创建一个名为 targetObject 的对象,然后在 res 上调用 GetType()
  • 对不起,我的错误。源代码已修复。
  • 您是否还可以从targetObject 类定义中添加一些sn-ps 代码,或者这无关紧要吗?
  • 你的targetObject类是从ContextBoundObject派生的吗?
  • 如果将定义更改为:[ServiceContract] public class WorkflowsManager : ContextBoundObject, IDisposable, IWorkflowManager,会发生什么?

标签: .net remoting appdomain


【解决方案1】:

感谢Panos Rontogiannis 的评论,我意识到我没有从您的问题中指出您实际上是在 WCF 代码中加载程序集,而不是在控制台应用程序中。

确保来自 GAC 的实际程序集版本是您希望在 WCF 代码中使用的版本。

我已经更新了类似于您的方案的解决方案。

//After building the library, add it to the GAC using "gacutil -i MyLibrary.dll"
using System;
using System.Runtime.Serialization;

namespace MyLibrary
{
    [Serializable]
    public class MyClass : MarshalByRefObject
    {
        public string Work(string name)
        {
            return String.Format("{0} cleans the dishes", name);
        }
    }
}

Web 应用程序中的服务类定义:

using System;
using System.Reflection;
using System.ServiceModel;

namespace WebApplication1
{
    [ServiceContract]
    public class MyService : IMyService
    {
        [OperationContract]
        public string DoWork(string name)
        {
            string methodName = "Work";
            object[] methodParams = new object[] { "Alex" };
            AppDomain appDomain = AppDomain.CreateDomain("");
            appDomain.Load("MyLibrary, Version=1.0.0.3, Culture=neutral, PublicKeyToken=0a6d06b33e075e91");
            string typeAssembly = "MyLibrary, Version=1.0.0.3, Culture=neutral, PublicKeyToken=0a6d06b33e075e91";
            string typeName = "MyLibrary.MyClass";
            object targetObject = appDomain.CreateInstanceAndUnwrap(typeAssembly, typeName);
            MethodInfo methodInfo = targetObject.GetType().GetMethod(methodName);
            string result = methodInfo.Invoke(targetObject, methodParams).ToString();
            return result;
        }
    }
}

调用 WCF 服务的控制台应用程序:

using System;
using WebApplication1;

namespace ConsoleApplication12
{
    class Program
    {
        static void Main(string[] args)
        {
            WebApplication1.MyService myService = new MyService();
            Console.WriteLine(myService.DoWork("Alex"));
        }
    }
}

【讨论】:

  • 我认为 OP 希望您在 Main 添加的代码从 WCF 服务中执行。
  • 谢谢@PanosRontogiannis,我完全想念它了。
  • 我不会将程序集放置到 GAC。 GetSomehowAppDomain(); 将程序集加载到新创建的 AppDomain 从众所周知的地方。
猜你喜欢
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多