Configuring Unity container using XML or web.config - c#

I'm working with .net 4.5 and MVC4.
I implemented Unity IoC as described in the following post: http://kennytordeur.blogspot.com/2011/05/aspnet-mvc-3-and-unity-using.html
But I would like to be able to have "register" my repository types using an external XML or within web.config. Is that possible?, samples would be greatly appreciated.
thanks

Unless there is a really strong reason to, you should register as much as possible in code. XML configuration is much more error prone, verbose and can become a maintenance nightmare very quickly. Instead of registering (all) your repository types in XML (which is possible with Unity), just put the assembly name containing that contains the repository types in the config and register them dynamically in code. This saves you from having to change the configuration every time you add a new repository implementation.
Here is an example.
In your configuration file, add a new appSetting with the name of the assembly:
<appSettings>
<add key="RepositoryAssembly" value="AssemblyName" />
</appSettings>
In your composition root, you can do the following:
var assembly = Assembly.LoadFrom(
ConfigurationManager.AppSettings["RepositoryAssembly"]);
// Unity misses a batch-registration feature, so you'll have to
// do this by hand.
var repositoryRegistrations =
from type in assembly.GetExportedTypes()
where !type.IsAbstract
where !type.IsGenericTypeDefinition
let repositoryInterface = (
from _interface in type.GetInterfaces()
where _interface.IsGenericType
where typeof(IRepository<>).IsAssignable(
_interface.GetGenericTypeDefinition())
select _interface)
.SingleOrDefault()
where repositoryInterface != null
select new
{
service = repositoryInterface,
implemention = type
};
foreach (var reg in repositoryRegistrations)
{
container.RegisterType(reg.service, reg.implementation);
}
The LINQ query has a lot of subtle defects (for instance, it lacks checks for generic type constraints), but it will work for the common scenarios. If you work with generic type constraints, you should definitely switch to a framework that has support for this, because this is something that's really hard to get right.

Related

Injecting and modifying C# executable

I would like to ask if it is possible to somehow inject C# code to an existing *.exe file that is also written in C# without decompiling it.
In other words, I'm trying to make an "extension" to an already existing C# program, but I would like to modify it without any manipulation with the "base" code (the .*exe file).
Is there any way to accomplish this? Or is the decompilation process required to modify base code's methods, classes and/or add extensions to it, etc. ?
you can achieve it by using frameworks like Mono.Cecil or Microsoft CCI project. These frameworks allows you to read & modify/inject IL. But it's not easy to learn those frameworks and IL codes usage.
Thought there's a library available FluentIL which is build on top of Mono.Cecil provides C# wrapper for IL Code. It doesn't Decompile the assembly rather it loads it, inject the assembly can writes/generates a new one with injected code.
Here's a sample that I used to inject "Null Checking code" in methods where arguments are marked with [NotNull] in project assembly post compilation.
var assembly = AssemblyDefinition.ReadAssembly(SourceAssemblyPath);
var module = assembly.MainModule;
var q = from type in module.Types
from method in type.Methods
from parameter in method.Parameters
where parameter.HasCustomAttributes
from attribute in parameter.CustomAttributes
where attribute.AttributeType.FullName == NotNullAttribute.FullName
select new { Method = method, Parameter = parameter };
foreach (var item in q)
{
item.Method.InsertBefore()
.Ldarg(item.Parameter.Name)
.IfNull()
.Throw<ArgumentNullException>()
.EndIf();
}
SourceAssemblyPath = SourceAssemblyPath.Replace("\\debug\\", "\\release\\");
assembly.Write(SourceAssemblyPath, new WriterParameters { WriteSymbols = false });

Is there a LINQ Query Provider for querying C# files?

Is there such a thing as a LINQ Query Provider for querying C# files?
I have a Winforms app that I use to assist me in generating code as well as to supplement Visual Studio's editing capabilities for existing code. One thing I would like to be able to do is to query a given class to see if a method exists. Or query for a list of classes, or query for classes with a particular type in the method signature, etc.
Further, I would love to be able to run the usual CRUDs on said C# files, but I realize that this may be out of scope for this question.
SOLVED!
Thanks to the folks who suggested Roslyn, and especially thanks to the code sample provided by Konrad Kokosa below, I was able to get exactly what I needed.
First thing you need to do is download the Roslyn DLLs (I used NuGet). Then query away. Here is another example for getting an alphabetized list of all methods in a class:
static List<string> GetMethodList(string filename, string className)
{
var syntaxTree = SyntaxTree.ParseFile(filename);
var root = syntaxTree.GetRoot();
var #class = root.DescendantNodes().OfType<ClassDeclarationSyntax>().FirstOrDefault(md => md.Identifier.ValueText.Equals(className));
return (List<string>) #class.DescendantNodes().OfType<MethodDeclarationSyntax>().ToList().OrderBy(m => m.Identifier.ValueText).Select(m => m.Identifier.ValueText);
}
I've found Roslyn very intuitive. Here is an example of parsing source file for a specified methodName within specified class className:
static void GetClassMethod(string filename, string className, string methodName)
{
var syntaxTree = SyntaxTree.ParseFile(filename);
var root = syntaxTree.GetRoot();
var #class = root.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.Where(md => md.Identifier.ValueText.Equals(className))
.FirstOrDefault();
var method = #class.DescendantNodes()
.OfType<MethodDeclarationSyntax>()
.Where(md => md.Identifier.ValueText.Equals(methodName))
.FirstOrDefault();
}
From this example you can easily build querying all classes withing a file.
Microsoft is working on a project called Roslyn which allows you to interact with C# code via ordinary .NET objects:
http://msdn.microsoft.com/en-us/vstudio/roslyn.aspx
It hasn't been officially released, though, and I'm honestly not sure that it would include things like manipulating the source files (for example, to add a function to a class).
If you're working with code that is already compiled, you could probably use a combination of a few tricks, such as loading an assembly at runtime and then using reflection to interrogate it.
However, I would suggest taking a look at tools that are already available for generating code, like T4 Templates. There might be a better way to solve the underlying problem than interrogating C# source files.

MEF attribute-less property importing with contract name

I find the lambda expressions needed for importing of properties somewhat confusing and I am trying to also understand how to use MEF conventions for importing and exporting so maybe I am trying to take on too much at once.
I am exporting ResourceDictionary with a contract name which I imported previously like this:
[ImportMany("ApplicationResources", typeof(ResourceDictionary))]
public IEnumerable<ResourceDictionary> Views { get; set; }
Which works well and is fine, however I am now trying to import this via a RegistrationBuilder but not fully understanding how to do this.
This exports them I believe (but I have to be honest I don't fully understand the syntax):
var registration = new RegistrationBuilder();
registration.ForTypesDerivedFrom<ResourceDictionary>()
.Export<ResourceDictionary>(x => x.AsContractName("ApplicationResources"));
I have a property in my App that I wish to populate
So tried this (carried out within the App itself)
registration.ForType<App>()
.ImportProperty<ResourceDictionary>(x => x.Views);
But this isn't working and I am guessing I need to set contract name somehow? Can anyone tell me what the syntax for this is? Maybe if I can see the correc syntax I can better understand how it works... I hope!
Typically it turns out that I found the solution after posting the question. I don't tend to answer my own questions but as it had me stuch for a while and in case it helps anyone else this is what works:
registration.ForType<App>()
.ImportProperty<ResourceDictionary>(x => x.Views, ib => ib.AsContractName("ApplicationResources"));
However this only works if I use SafisfyImportsOnce rather than ComposeParts which I am slightly confused about

Using Autofac and multiple WithMetadata assignments

I am trying to use Autofac specifying 2 metadata items. It seems to add these fine, however, I am not too clear on how to retrieve the service by specifying both of these items. I have metadata items for an Assembly Name and a Version. The registration snippet is as follows:
builder.RegisterAssemblyTypes(assembly).Where(
t => t.GetInterfaces().Any(i =>
plugin.Interface == i.Name)).As<IPlugin>()
.WithMetadata<IMetaDataName>(m => m.For(pn => pn.Name, name)
.WithMetadata<IMetaDataVersion>(m => m.For(pn => pn.Version, version)
The only documentation and examples I can find specify that I can use this syntax:
IEnumerable<Lazy<IPlugin, IMetaDataName>>
in the costructor of the class or in a class that resolves the service I am after. What I am after is a mechanism to let me do the following:
Get the service that has the MetaDataName == "Service1" AND MetaDataVersion == "1.4"
Currently I have concatenated the two together for 1 metadata type which works but feels clunky. Is there are better approach to this?
Thanks
Craig.
Rather than concatenate both interfaces into one, you can just create a separate concatenated interface for the importer.
The interface name used at registration time doesn't have to match the one used as a dependency - the property names are the only shared information at this point.
The metadata view type used in a dependency is really specific to the class receiving the dependency rather than the type providing it, so these can vary independently.
Know this isn't exactly the answer you were looking for but hope it helps.

How to find all methods in assembly that instantiate object of class X?

Interesting question here: In my current project we're using a custom performance monitoring suite that is very config-heavy (it uses Perfmon so we have to manually register each performance counter. There is one performance counter for each method that we monitor, and there are a lot of those).
I was wondering if there are any tools that would, say, allow me to analyse the project assembly, find all methods that instantiate an instance of class XClass, then write them out to a file? This would allow me to cut down the amount of manual config I need to do by a large margin.
Thanks, Ed
EDIT
Sorry, the 'write them to a file' thing was a little contrived: really I need to reformat them with some extra data and write them in a config-specific XML format. This would be best if I can code it up so it can be set as a build task (so I don't have to run it manually) and any future changes can be made easily and documented etc.
Open the assembly in Reflector (the free version is fine); find the type (F3), then bring up the anaylyzer (Ctrl+R) and expand the "Instantiated By" node.
Then right-click on the "Instantiated By" node itself and click copy; for example:
System.Data.SqlClient.SqlConnectionStringBuilder
Depends On
Used By
Exposed By
Instantiated By
SqlDependencyProcessDispatcher.GetHashHelper(String, SqlConnectionStringBuilder&, DbConnectionPoolIdentity&, String&, String) : SqlConnectionContainerHashHelper
System.Data.SqlClient.SqlClientFactory.CreateConnectionStringBuilder() : DbConnectionStringBuilder
System.Web.Management.SqlWebEventProvider.Initialize(String, NameValueCollection) : Void
System.Web.SessionState.SqlSessionStateStore.CreatePartitionInfo(String) : IPartitionInfo
System.Web.SessionState.SqlSessionStateStore+SqlPartitionInfo.get_TracingPartitionString() : String
System.Web.SessionState.SqlSessionStateStore+SqlStateConnection..ctor(SqlPartitionInfo, TimeSpan)
If you need to write code to automate your task, it's easy to do it with Mono.Cecil. As an example, this code searches through all the methods of the top level types of an assembly for the instantiation of a class Foo.Bar.Baz:
using Mono.Cecil;
using Mono.Cecil.Cil;
// ...
static void SearchMethod (MethodDefinition method)
{
foreach (var instruction in method.Body.Instructions) {
if (instruction.OpCode != OpCodes.Newobj)
continue;
var constructor = (MethodReference) instruction.Operand;
if (constructor.DeclaringType.FullName != "Foo.Bar.Baz")
continue;
Console.WriteLine ("new Foo.Bar.Baz in {0}", method.FullName);
}
}
static void Main ()
{
var module = ModuleDefinition.ReadModule ("Foo.Bar.dll");
var methods = module.Types.SelectMany (t => t.Methods).Where (m => m.HasBody);
foreach (var method in methods)
SearchMethod (method);
}
Take a look at NDepend. It's a static analysis tool with a very powerful query language: CQL (Code Query Language).
Update
NDepend has a console application that can be prodded for automation (e.g. for use in a build systems) and can output reports to file.
An example query to find methods which instantiate a defined type:
SELECT METHODS WHERE CreateA "MyNamespace.MyClass"
You probably want to change your design so that they use a factory instead, such that the factory is responsible for the extra bookkeeping.
That said, you can look in the System.Reflection namespace, (from memory), where the Assembly class is used.

Categories

Resources