现在的位置: 首页 > 综合 > 正文

某项目要调用现有的100多个DLL 三 先解决为一个类型做一个跨域的问题

2013年01月26日 ⁄ 综合 ⁄ 共 2321字 ⁄ 字号 评论关闭

将同类的操作Wrap在同一个类型中,如以下代码:

/// <summary>
/// really business operation.
/// </summary>
[Serializable]
public class ServiceWrapper1 : MarshalByRefObject
{
protected ServiceWrapper1()
{
}

public virtual List<OpaOutput> GetUserDto(OpaInput input)
{

Console.WriteLine(AppDomain.CurrentDomain.FriendlyName
+ " Test2"); //show current domain
OPATest test = new OPATest();
return test.GetUserDto(input);
}
}
}

这是一个简单的wrap  用于调用另外一个dll的OPATest 类 , 同时测试一下代码是否运行在独立的域中

构造函数变为Protected的主要原因是禁止直接通过构造函数新建wrap实例,强迫通过DefaultInstance的方式调用代码 (这样才是应用程序隔离的)

不变成Private的原因是之后还需要有继承 如果把父类的构造函数设置为private 那么子类也构造不了

但是在当前代码中 你应该把protected改为public 才可以正常的运行, 

为了解决跨域的问题 将wrap类继承于 MarshalByRefObject ,

OpaInput和 OpaOutput分别是输入输出参数 (定义在现有的dll中 为了方便开发 先暂时定义为可以序列化,真正的序列化实现的问题稍后解决)以下是他们的定义

namespace ClassLibrary2
{

public class OPATest
{
public List<OpaOutput> GetUserDto(OpaInput input)
{
return new List<OpaOutput> {
new OpaOutput() { Date=DateTime.Now },
new OpaOutput(){Date=DateTime.Now},
new OpaOutput(){Date=DateTime.Now},
};
}
}
[Serializable]
public class OpaOutput
{
public string Name { get; set; }
public string Content;
public int Type;
public DateTime Date { get; set; }
}
[Serializable]
public class OpaInput
{
public string UserCode { get; set; }
public string Content;
public int? Type;
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
}

为了方便的访问跨域的dll 实现了以下类型

[Serializable]
public class BaseWrapper<T> : MarshalByRefObject
{
/// <summary>
/// define a application domain for every T
/// </summary>
private static AppDomain _CurrentDomian = null;

/// <summary>
/// static constructor
/// </summary>
static BaseWrapper()
{
string domainName = "Application Execution Domain " + typeof(T).FullName;
_CurrentDomian
= AppDomain.CreateDomain(domainName, null, null);
}

/// <summary>
/// forbid call constructor directly.
/// </summary>
protected BaseWrapper()
{
}

/// <summary>
/// singleton instance.
/// </summary>
public static T DefaultInstance
{
get
{
return (T)_CurrentDomian.CreateInstanceAndUnwrap(typeof(T).Assembly.FullName, typeof(T).FullName);
}
}

}

那么跨域的调用就非常简单了,并且为一个类型T维护一个ApplicationDomain

调用代码如下所示:

BaseWrapper<ServiceWrapper1>.DefaultInstance.GetUserDto(new ClassLibrary2.OpaInput() { Content = "123" });

非常的简单 和原来的调用代码相比 增加的代码量一点都不多,原来的调用代码如下所示

ServiceWrapper1 s = new ServiceWrapper1();
s.GetUserDto(
new ClassLibrary2.OpaInput() { Content = "123" });

最终运行结果如下:

Application Execution Domain ClassLibrary1.ServiceWrapper1 Test2

说明 这个方法是在新的应用程序域中执行 

PS:这里做了一个假设 即输入输出删除可序列化, 实际上不是所有的人声明代码的时候都会加上可序列化标签的 稍后我们来解决这个问题

那么到目前为止 我们把所有调用外部dll的代码集中到了一部分类里面,并且隔离在不同的应用程序域来执行了

【上篇】
【下篇】

抱歉!评论已关闭.