Creating WCF service by determining type at runtime - wcf

I am trying to create a WCF service without knowing its type/interface at runtime. To do this, I use ChannelFactory. ChannelFactory is a generic class so I need to use Type.MakeGenericType. The type I pass to MakeGenericType is from a list of interfaces I previously gathered with reflection by searching some assemblies.
Ultimately, I call MethodInfo.Invoke to create the object. The object is created just fine, but I cannot cast it to the proper interface. Upon casting, I receive the following error:
"Unable to cast transparent proxy to type 'Tssc.Services.MyType.IMyType'"
After some experimenting, I have found that the interface/type passed to MakeGenericType seems to be the problem. If I substitute the interface in my list with the actual interface, then everything works fine. I have combed through the two objects and cannot see a difference. When I modify the code to produce both types, comparing them with Equals returns false. It is unclear to me whether Equals is just checking that they are referring to the same object (not) or thety are checking all properties, etc.
Could this have something to do with how I gathered my interfaces (Reflection, saving in a list...)? A comparison of the objects seems to indicate they are equivalent. I printed all properties for both objects and they are the same. Do I need to dig deeper? If so, into where?
// createService() method
//*** tried both of these interfaces, only 2nd works - but they seem to be identical
//Type t = interfaces[i]; // get type from list created above - doesn't work
Type t = typeof(Tssc.Services.MyType.IMyType); // actual type - works OK
// create ChannelFactory type with my type parameter (t)
Type factoryType = typeof(ChannelFactory<>);
factoryType = factoryType.MakeGenericType(new Type[] { t });
// create ChannelFactory<> object with two-param ctor
BasicHttpBinding binding = new BasicHttpBinding();
string address = "blah blah blah";
var factory = Activator.CreateInstance(factoryType, new object[] { binding, address });
// get overload of ChannelFactory<>.CreateChannel with no parameters
MethodInfo method = factoryType.GetMethod("CreateChannel", new Type[] { });
return method.Invoke(factory, null);
//--------------- code that calls code above and uses its return
object ob = createService();
//*** this cast fails
Tssc.Services.MyType.IMyType service = (Tssc.Services.MyType.IMyType)ob;

Ok, I understand whats happening here - the problem is relating to loading the same assembly being effectively loaded twice - once via a reference, and once via the assembly load command. What you need to do is change the place where you load your assembly, and check to see if it already exists in the current AppDomain, like this maybe:
Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals("ClassLibrary1Name"));
if (assembly == null)
{
assembly = System.Reflection.Assembly.LoadFile("path to your assembly");
}
//do your work here
This way if the assembly is already loaded into memory, it'll use that one.

Related

Efficient way to bring parameters into controller action URL's

In ASP.Net Core you have multiple ways to generate an URL for controller action, the newest being tag helpers.
Using tag-helpers for GET-requests asp-route is used to specify route parameters. It is from what I understand not supported to use complex objects in route request. And sometimes a page could have many different links pointing to itself, possible with minor addition to the URL for each link.
To me it seems wrong that any modification to controller action signature requires changing all tag-helpers using that action. I.e. if one adds string query to controller, one must add query to model and add asp-route-query="#Model.Query" 20 different places spread across cshtml-files. Using this approach is setting the code up for future bugs.
Is there a more elegant way of handling this? For example some way of having a Request object? (I.e. request object from controller can be put into Model and fed back into action URL.)
In my other answer I found a way to provide request object through Model.
From the SO article #tseng provided I found a smaller solution. This one does not use a request object in Model, but retains all route parameters unless explicitly overridden. It won't allow you to specify route through an request object, which is most often not what you want anyway. But it solved problem in OP.
<a asp-controller="Test" asp-action="HelloWorld" asp-all-route-data="#Context.GetQueryParameters()" asp-route-somestring="optional override">Link</a>
This requires an extension method to convert query parameters into a dictionary.
public static Dictionary GetQueryParameters(this HttpContext context)
{
return context.Request.Query.ToDictionary(d => d.Key, d => d.Value.ToString());
}
There's a rationale here that I don't think you're getting. GET requests are intentionally simplistic. They are supposed to describe a specific resource. They do no have bodies, because you're not supposed to be passing complex data objects in the first place. That's not how the HTTP protocol is designed.
Additionally, query string params should generally be optional. If some bit of data is required in order to identify the resource, it should be part of the main URI (i.e. the path). As such, neglecting to add something like a query param, should simply result in the full data set being returned instead of some subset defined by the query. Or in the case of something like a search page, it generally will result in a form being presented to the user to collect the query. In other words, you action should account for that param being missing and handle that situation accordingly.
Long and short, no, there is no way "elegant" way to handle this, I suppose, but the reason for that is that there doesn't need to be. If you're designing your routes and actions correctly, it's generally not an issue.
To solve this I'd like to have a request object used as route parameters for anchor TagHelper. This means that all route links are defined in only one location, not throughout solution. Changes made to request object model automatically propagates to URL for <a asp-action>-tags.
The benefit of this is reducing number of places in the code we need to change when changing method signature for a controller action. We localize change to model and action only.
I thought writing a tag-helper for a custom asp-object-route could help. I looked into chaining Taghelpers so mine could run before AnchorTagHelper, but that does not work. Creating instance and nesting them requires me to hardcode all properties of ASP.Net Cores AnchorTagHelper, which may require maintenance in the future. Also considered using a custom method with UrlHelper to build URL, but then TagHelper would not work.
The solution I landed on is to use asp-all-route-data as suggested by #kirk-larkin along with an extension method for serializing to Dictionary. Any asp-all-route-* will override values in asp-all-route-data.
<a asp-controller="Test" asp-action="HelloWorld" asp-all-route-data="#Model.RouteParameters.ToDictionary()" asp-route-somestring="optional override">Link</a>
ASP.Net Core can deserialize complex objects (including lists and child objects).
public IActionResult HelloWorld(HelloWorldRequest request) { }
In the request object (when used) would typically have only a few simple properties. But I thought it would be nice if it supported child objects as well. Serializing object into a Dictionary is usually done using reflection, which can be slow. I figured Newtonsoft.Json would be more optimized than writing simple reflection code myself, and found this implementation ready to go:
public static class ExtensionMethods
{
public static IDictionary ToDictionary(this object metaToken)
{
// From https://geeklearning.io/serialize-an-object-to-an-url-encoded-string-in-csharp/
if (metaToken == null)
{
return null;
}
JToken token = metaToken as JToken;
if (token == null)
{
return ToDictionary(JObject.FromObject(metaToken));
}
if (token.HasValues)
{
var contentData = new Dictionary();
foreach (var child in token.Children().ToList())
{
var childContent = child.ToDictionary();
if (childContent != null)
{
contentData = contentData.Concat(childContent)
.ToDictionary(k => k.Key, v => v.Value);
}
}
return contentData;
}
var jValue = token as JValue;
if (jValue?.Value == null)
{
return null;
}
var value = jValue?.Type == JTokenType.Date ?
jValue?.ToString("o", CultureInfo.InvariantCulture) :
jValue?.ToString(CultureInfo.InvariantCulture);
return new Dictionary { { token.Path, value } };
}
}

List of DisposableLazy`2 does not have 'Add' method when called using dynamic variable

Problem
I am facing a problem using dynamically created list of items when Add method is called on dynamicvariable. Consider following code.
IEnumerable<dynamic> plugins = (IEnumerable<dynamic>)field.GetValue(instance);
if (plugins == null)
continue;
dynamic filteredPlugins = null;
foreach (var plugin in plugins)
{
if (filteredPlugins == null)
filteredPlugins = Activator
.CreateInstance(typeof(List<>)
.MakeGenericType(plugin.GetType()));
if (/* this condition does not matter*/)
//filteredPlugins.Add(plugin);
filteredPlugins.GetType().GetMethod("Add")
.Invoke(filteredPlugins, new object[] { plugin });
}
And now, the commented line filteredPlugins.Add(plugin) will throw System.Reflection.TargetInvocationException with the message 'object' does not contain a definition for 'Add' when plugin is of type
System.ComponentModel.Composition.ExportServices.DisposableLazy<IPlugin,IMetadata>
but it works completely perfect when pluginis of type
System.Lazy<IPlugin, IMetadata>
When the reflection is used to call Add method on the instance filteredPlugins instance as is done on the next line - everything works fine for any type.
My question is WHY is not Add method found in case of DisposableLazy type.
Background
This code is part of the method that I use in OnImportsSatisfied() method. I am using two kinds of import - which differs only in RequiredCreationPolicy - on has CreationPolicy.NonShared and the other default value of CreationPolicy.Any.
[ImportMany(RequiredCreationPolicy = CreationPolicy.NonShared)]
private IEnumerable<Lazy<IPlugin, IMetadata>> plugins = null;
For CreationPolicy.NonShared fields the underlaying type in the plugins is DisposableLazy and for CreationPolicy.Any the underlaying type in the plugins is Lazy.
Edit: As asked in the answer - I am using dynamic variable because IPlugin interface can change everytime this method is called and they do not have to have anything in common.
Edit2: I just found similar question C# dynamic type gotcha, so this can be probably closed as duplicite.
Because System.ComponentModel.Composition.ExportServices.DisposableLazy is a private class, the runtime binder is having trouble believing you have permission to use type, where reflection doesn't care.
Which begs the question why are you using dynamics at all in this case. Since DisposableLazy<IPlugin,IMetadata> public interface is it's subclass Lazy<IPlugin, IMetadata> & IDisposable, shouldn't you just be using a List<Lazy<IPlugin, IMetadata>> for either case?
var plugins = (IEnumerable<Lazy<IPlugin, IMetadata>>)field.GetValue(instance);
if (plugins == null)
continue;
var filteredPlugins = new List<Lazy<IPlugin, IMetadata>>();
foreach (var plugin in plugins)
{
if (/* this condition does not matter*/)
filteredPlugins.Add(plugin);
}
}

How to extract class IL code from loaded assembly and save to disk?

How would I go about extracting the IL code for classes that are generated at runtime by reflection so I can save it to disk? If at all possible. I don't have control of the piece of code that generates these classes.
Eventually, I would like to load this IL code from disk into another assembly.
I know I could serialise/deserialise classes but I wish to use purely IL code. I'm not fussed with the security implications.
Running Mono 2.10.1
Or better yet, use Mono.Cecil.
It will allow you to get at the individual instructions, even manipulating them and disassembling them (with the mono decompiler addition).
Note that the decompiler is a work in progress (last time I checked it did not fully support lambda expressions and Visual Basic exception blocks), but you can have pretty decompiled output in C# pretty easily as far as you don't hit these boundary conditions. Also, work has progressed since.
Mono Cecil in general let's you write the IL to a new assembly, as well, which you can then subsequently load into your appdomain if you like to play with bleeding edge.
Update I came round to trying this. Unfortunately I think I found what problem you run into. It turns out there is seems to be no way to get at the IL bytes for a generated type unless the assembly happened to get written out somewhere you can load it from.
I assumed you could just get the bits via reflection (since the classes support the required methods), however the related methods just raise an exception The invoked member is not supported in a dynamic module. on invocation. You can try this with the code below, but in short I suppose it means that it ain't gonna happen unless you want to f*ck with Marshal::GetFunctionPointerForDelegate(). You'd have to binary dump the instructions and manually disassemble them as IL opcodes. There be dragons.
Code snippet:
using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System.Reflection.Emit;
using System.Reflection;
namespace REFLECT
{
class Program
{
private static Type EmitType()
{
var dyn = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Emitted"), AssemblyBuilderAccess.RunAndSave);
var mod = dyn.DefineDynamicModule("Emitted", "Emitted.dll");
var typ = mod.DefineType("EmittedNS.EmittedType", System.Reflection.TypeAttributes.Public);
var mth = typ.DefineMethod("SuperSecretEncryption", System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static, typeof(String), new [] {typeof(String)});
var il = mth.GetILGenerator();
il.EmitWriteLine("Emit was here");
il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
il.Emit(System.Reflection.Emit.OpCodes.Ret);
var result = typ.CreateType();
dyn.Save("Emitted.dll");
return result;
}
private static Type TestEmit()
{
var result = EmitType();
var instance = Activator.CreateInstance(result);
var encrypted = instance.GetType().GetMethod("SuperSecretEncryption").Invoke(null, new [] { "Hello world" });
Console.WriteLine(encrypted); // This works happily, print "Emit was here" first
return result;
}
public static void Main (string[] args)
{
Type emitted = TestEmit();
// CRASH HERE: even if the assembly was actually for SaveAndRun _and_ it
// has actually been saved, there seems to be no way to get at the image
// directly:
var ass = AssemblyFactory.GetAssembly(emitted.Assembly.GetFiles(false)[0]);
// the rest was intended as mockup on how to isolate the interesting bits
// but I didn't get much chance to test that :)
var types = ass.Modules.Cast<ModuleDefinition>().SelectMany(m => m.Types.Cast<TypeDefinition>()).ToList();
var typ = types.FirstOrDefault(t => t.Name == emitted.Name);
var operands = typ.Methods.Cast<MethodDefinition>()
.SelectMany(m => m.Body.Instructions.Cast<Instruction>())
.Select(i => i.Operand);
var requiredTypes = operands.OfType<TypeReference>()
.Concat(operands.OfType<MethodReference>().Select(mr => mr.DeclaringType))
.Select(tr => tr.Resolve()).OfType<TypeDefinition>()
.Distinct();
var requiredAssemblies = requiredTypes
.Select(tr => tr.Module).OfType<ModuleDefinition>()
.Select(md => md.Assembly.Name as AssemblyNameReference);
foreach (var t in types.Except(requiredTypes))
ass.MainModule.Types.Remove(t);
foreach (var unused in ass.MainModule
.AssemblyReferences.Cast<AssemblyNameReference>().ToList()
.Except(requiredAssemblies))
ass.MainModule.AssemblyReferences.Remove(unused);
AssemblyFactory.SaveAssembly(ass, "/tmp/TestCecil.dll");
}
}
}
If all you want is the IL for your User class, you already have it. It's in the dll that you compiled it to.
From your other assembly, you can load the dll with the User class dynamically and use it through reflection.
UPDATE:
If what you have is a dynamic class created with Reflection.Emit, you have an AssemblyBuilder that you can use to save it to disk.
If your dynamic type was instead created with Mono.Cecil, you have an AssemblyDefinition that you can save to disk with myAssemblyDefinition.Write("MyAssembly.dll") (in Mono.Cecil 0.9).

Not able to filter WCF methods for dynamically created proxy

Some months back I was working on a project to display the WCF methods and thier parameters in a dropdown. At that time I was creating a proxy using Add Service Reference and hardcoded the service interface in the code.
How can I show all the methods that are available in my WCF in a dropdown
But when I try to create the proxy dynamically to do the same, the below code doesn't work. Please help me to show only the methods that was defined by me.
// Using Dynamic Proxy Factory by Vipul Modi # Microsoft
DynamicProxyFactory factory = new DynamicProxyFactory(txtService.Text);
// endpoints.
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name; //this is the service interface name, IAccountInfoService
}
DynamicProxy proxy = factory.CreateProxy(sContract);
Type proxyType = proxy.ProxyType;
MethodInfo[] methods = proxyType.GetMethods();
foreach (var method in methods)
{
//if (method.GetCustomAttributes(typeof(OperationContractAttribute), true).Length == 0)
// continue;
string methodName = method.Name;
ddlMethods.Items.Add(methodName);
}
The code commented method.GetCustomAttributes(typeof(OperationContractAttribute), true).Length doesn't work. It doesn't show any method. If I comment it out, then the result is all methods and variables. I want to restrict it to only user defined methods.
i dont know anything about DynamicProxyFactory but looking at http://blogs.msdn.com/b/vipulmodi/archive/2006/11/16/dynamic-programming-with-wcf.aspx it makes me think that
1) the proxy doesnt actually emit methods with the attribute. it doesn't seem to have a need to though i suppose you could tweak the code on your own to make that happen.
2) if you just want a list of method names, it seems you can get that from factory.Contracts

Returning wcf/json result from the wcf service

I Need by service contract to return the xml/json result depending on the request type.I also need a kind of helper function which will convert my result set (i am using linq to sql) so that i do not need to create the xml format for the result set by iterating through the table row many times.What is the suitable way to do that.
I need a kind of short cut method which will convert the table data to xml result.Had i been using asp.net mvc i would have been able to generate the xml data by overriding the the ExecuteResult method in the ActionResult and giving Conetnt-Type = "text/xml" as OP.But since i am using
Wcf i don't have the controller context(as controller context is the parameter that needs to be passed to Execute Result).
My present code for converting the table data to the xml format is below.
public XDocument UsersLists(string authToken)
{
bool IsAuthenticated = Authenticate(authToken);
XDocument xDoc = new XDocument();
XElement root = new XElement("Users");
if (IsAuthenticated)
{
List<User> lstUsers = _lService.UserRepository.GetUserCompanyFromAccountID(GetAccountId(authToken)).ToList();
if (lstUsers != null)
{
root.Add(new XElement("Message", "Success"));
foreach (var u in lstUsers)
{
XElement chid = new XElement("User");
root.Add(new XElement("UserId", u.UserId));
root.Add(new XElement("FirstName", u.FirstName));
root.Add(new XElement("LastName", u.LastName));
root.Add(new XElement("Email", u.Email));
root.Add(new XElement("CompanyName", u.Company.CompanyName));
root.Add(chid);
}
xDoc.Add(root);
return xDoc;
}
else
{
return ReturnFailure(xDoc, root);
}
}
else
{
return ReturnFailure(xDoc, root);
}
}
I need to eliminate this way of generating xml for each table records.
An early response is priceless.
Thanks
Technology : Windows Communication Foundation.
Implementation of single operation returning both XML or JSON differs between WCF 3.5 or WCF 4.0. For implementing this feature in WCF 3.5 check this thread. Generally you will have to create custom behavior and set the content type based on Accept header from the request. WCF 4.0 has native support for this feature. WebHttpBehavior has property AutomaticFormatSelectionEnabled. If you set this property to true it should just work out of the box.
To your second question. You don't need any custom formatting like in ASP.NET MVC. Formatting in WCF is handled by serialization. Just return collection from your operation and you will see what happens. Linq-To-Sql generated entities should be serializable by default. Just don't forget to execute query before returning from method. If you need special format of date which is not the same as Linq-To-Sql entities create custom data type which have public parameterless constructor and all required properties with getter and setter. If you want to make it clear makr that class with DataContract attribute and all properties with DataMember attribute. Return collection of that custom class instances from your operation.