我正在尝试在2个软件之间创建一种WCF通信(以挑战自己)。
我所说的WCF是指能够在共享库中具有作为契约的接口。然后可以在我的两个软件中使用该合同。 我想像在WCf中一样使用它们,这意味着客户端似乎在从同一软件中调用简单方法,但实际上是使用TcpClient在另一端调用TcpServer ....
作为WCF,我希望是通用的,所以我不希望预包装的类包装用于特定合同的网络逻辑。 作为WCF,我希望能够编写一个合约接口,然后使用我的合约作为模板参数创建一个诸如“ ClientBase”类的新实例,然后将该客户端用作我的其他软件的“远程”。 / p>
作为一个例子总是更好,这就是我想要的:
在共享项目中:
public interface IFooContract
{
void Add(int a, int b);
}
在客户端中:
class Program
{
static void Main(string[] args)
{
using (var client = new ClientFooContract())
{
var result = client.Add(5, 2);
}
}
}
class ClientFooContract : MyClientBase<IFooContract>, IFooContract, IDisposable
{
public int Add(int a, int b)
{
return Channel.Add(a, b);
}
}
class MyClientBase<T> where T : class
{
protected T Channel;
public MyClientBase()
{
Channel = /*Create Channel instance*/
}
}
我的实现确实接近WCF的基础,但是我的问题是创建Channel Instance,因为我当然没有可以实例化的任何类。我需要一种动态类来实现该特定合同的实现,并针对该合同的每种方法,处理用于创建TcpClient,将其连接到远程服务器,发送数据,等待响应并将结果返回给ClientFooContract的网络逻辑。 / p>
当然,我可以创建一个实现合同并为每种方法处理网络的ChannelBase类,但是我希望能够像WCF一样通用,因为它能够为我的系统提供任何类型的合同。
我目前正在使用Emit命名空间,试图立即构建包含方法的动态类,这里是我尚未完成的用于创建方法的代码:
class Program
{
static void Main(string[] args)
{
var methods = new List<Method>();
methods.Add(new Method()
{
Name = "Add",
Params = new List<MethodParam>()
{
new MethodParam()
{
Name = "a",
Type = typeof(int)
},
new MethodParam()
{
Name = "b",
Type = typeof(int)
}
},
ReturnType = typeof(int)
});
MyTypeBuilder.CompileResultType(methods);
}
}
public class Method
{
public string Name;
public List<MethodParam> Params;
public Type ReturnType;
}
public class MethodParam
{
public string Name;
public Type Type;
}
public static class MyTypeBuilder
{
public static Type CompileResultType(List<Method> methodList)
{
TypeBuilder tb = GetTypeBuilder();
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
if (methodList != null)
foreach (var method in methodList)
CreateMethod(tb, method);
Type objectType = tb.CreateType();
return objectType;
}
private static TypeBuilder GetTypeBuilder()
{
var typeSignature = "MyDynamicType";
var an = new AssemblyName(typeSignature);
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
//AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
null,
new Type[] { typeof(IFoo) });
return tb;
}
private static void CreateMethod(TypeBuilder tb, Method method)
{
MethodBuilder methodBuilder = tb.DefineMethod(method.Name, MethodAttributes.Public, method.ReturnType, method.Params.Select(l => l.Type).ToArray());
ILGenerator il = methodBuilder.GetILGenerator();
}
}
这是我的难题,我不知道如何在我的动态方法中添加主体,我在互联网上发现了一些关于如何创建局部变量的示例,等等,但是实际上我该如何用IL创建一个TcpClient,我需要吗将所有这些放置在单独的方法中,然后调用此方法?如何 ? 我实际上如何简单地调用console.writeLine来实际测试我的系统?
我的问题实际上是MethodBody的创建,因为我将不得不在这里做很多工作,而不仅仅是声明局部变量和处理基本操作。 如果至少有一种方法可以在另一个类上调用另一个方法,那么将很有帮助
如果您什么都不知道,谢谢您的帮助
答案 0 :(得分:0)
经过几个小时的测试,我终于找到了解决方法主体问题的方法。
此处带有评论(以防万一,某天结束于本主题)。
class Program
{
static void Main(string[] args)
{
// Init List of method that I want to create
var methods = new List<Method>();
methods.Add(new Method()
{
Name = "Add",
Params = new List<MethodParam>()
{
new MethodParam()
{
Name = "a",
Type = typeof(int)
},
new MethodParam()
{
Name = "b",
Type = typeof(int)
}
},
ReturnType = typeof(int)
});
// Compile my type
var myType = MyTypeBuilder.CompileResultType(methods);
// Create instance of my type
var myObject = Activator.CreateInstance(myType) as IFooContract;
// Call Function
var result = myObject.Add(5, 2);
// Log
Console.WriteLine(result);
Console.Read();
}
}
// Used to store Method Infos
public class Method
{
public string Name;
public List<MethodParam> Params;
public Type ReturnType;
}
// Used to store Method param's Infos
public class MethodParam
{
public string Name;
public Type Type;
}
// Builder for the Dynamic class
public static class MyTypeBuilder
{
public static Type CompileResultType(List<Method> methodList)
{
TypeBuilder tb = GetTypeBuilder();
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
if (methodList != null)
{
// Loop throught all method definition
foreach (var method in methodList)
{
// Generate new method on the dynamic class
CreateMethod(tb, method);
}
}
// Create the Dynamic class
Type objectType = tb.CreateType();
return objectType;
}
private static TypeBuilder GetTypeBuilder()
{
var typeSignature = "MyDynamicType";
var an = new AssemblyName(typeSignature);
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
null,
new Type[] { typeof(IFooContract) }); // <= Interface that the Dynamic class will implement (used for intellisens)
tb.AddInterfaceImplementation(typeof(IFooContract)); // <= Specify that the class will implement that interface
return tb;
}
private static void CreateMethod(TypeBuilder tb, Method method)
{
// Create Method builder
MethodBuilder mb = tb.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, method.Params.Select(x => x.Type).ToArray());
// Get the IL Generator
ILGenerator il = mb.GetILGenerator();
// Start Build Method Body :
// Load first parameter on evaluation stack
il.Emit(OpCodes.Ldarg_1);
// Load Second parameter on evaluation stack
il.Emit(OpCodes.Ldarg_2);
// Use the two last element loaded as operand for "+" operation
il.Emit(OpCodes.Add);
// Push the last element on evaluation stack as return of the function
il.Emit(OpCodes.Ret);
// Stop Build Method Body
// Explicitly set this new function as the implementation of the interface function
MethodInfo interfaceMethod = typeof(IFooContract).GetMethod(method.name);
tb.DefineMethodOverride(mb, interfaceMethod);
}
}