How do I register types in assemblies that haven't been loaded with Unity? - unity-container

I want to load all the types of an Interface so I can call a method on it. However, the assemblies are not referenced a compile time. They will be in the bin folder.
Is this something I can do easily with Unity?
So for example I have code sort of like:
using (var container = new UnityContainer())
{
container.RegisterType<IModule>();
var modules = container.ResolveAll(typeof(IModule));
foreach (IModule module in modules) { module.Logon(); }
Console.WriteLine("Done...");
Console.ReadLine();
}
Of course, modules resolves to nothing because the assemblies have been just dropped into the bin folder. They are not statically referenced in my current assembly.
Or, do I have to do some type of Assemblies.LoadAssembly(). I'd like this to be as dynamic as possible. I don't have to have to specify assembly names in a config file or code if possible.
Thanks in advance.

Unity does not, by itself, load any assemblies. It works off Type objects and lets the CLR load those types however it wants to.
To do dynamic discovery like you want, you'll need to write a little code to spin through the assemblies in the bin directory, load them into memory, and then spin through them looking for the types you're interested in. It's pretty trivial if you're familiar with the reflection APIs.
Here's some code you can use to loop through the bin directory and make sure every assembly there is loaded:
private static bool ForceLoadAssemblies()
{
foreach (var fileName in Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll"))
{
string assemblyName = Path.GetFileNameWithoutExtension(fileName);
if (assemblyName != null)
{
Assembly.Load(assemblyName);
}
}
return true;
}
Another option would be to look at MEF instead. MEF was explicitly designed for the dynamic discovery case, while Unity is more built around internal dependency management.

Related

Distinguish between SpecFlow and Unit Test assembly

I have written some code that analyzes a test DLL and extracts names of tests and which tags they have using reflection.
I originally wrote it to analyze SpecFlow DLLs, but it seems to work fine for Unit Test DLLs, with a few tweaks.
Both are using MSTest (VSTest.Console.exe)
I am wondering if anyone knows how I could distinguish one type of assembly from the other, so that I can use the same code to analyze either kind of assembly, without having to specify what kind it is.
Also, if anyone knows of an existing tool to do this (Extract lists of tests from DLLs), that would be great. I am kind of feeling like I must be re-inventing the wheel here...
Sample files
Specflow DLL
Unit Test DLL
(You probably need to right-click these and unblock to be able to load them)
TLDR: How do I detect, through code, which one of these DLLs is Specflow and which is Unit Tests?
Duh, it was actually quite simple
public static bool IsSpecflowDll(Assembly assembly)
{
var references = assembly.GetReferencedAssemblies();
foreach (var reference in references)
{
if (reference.Name == "TechTalk.SpecFlow")
{
return true;
}
}
return false;
}

Pass objects to application from HttpModule

Is there a way to create objects in HTTP module and pass those objects to applications.
I can use HTTPContext.Items. But that means I will reference System.Web in any DLL in the application that will use those data. Utility.dll is reading data generated by the http module, and I don't want to reference System.Web in that DLL because it is used by both web and desktop applications.
of course Desktop applications will not find the object, this is not a problem.
You can use the new and extensible cache API in System.Runtime.Caching, namely, the MemoryCache class. Just use a shared constant as the name and you're done.
I think your web module should communicate with Utility.dll and not the other way around. It should call a function inside Utility.dll with the data it needs. Since we don't know much about the nature of your application and that you didn't provide much information about how you want your different modules to communicate, it hard to give a definite answer.
The Utility.dll module could have a method accepting data like
public void QueueProcessingData(YourDataType[] data) {/* ... */}
If you really want your Utility.dll module to pull data from the web server, then you could use the builtin cache like #Ricardo Peres said. Example of using the builtin MemoryCache:
var data = "object your web module created and you want to pass to utility.dll";
ObjectCache cache = MemoryCache.Default;
cache.Add("The name you want", data, new CacheItemPolicy { AbsoluteExpiration = DateTime.MaxValue });
That way your other modules don't have to reference System.Web
HttpContext.Items is an IDictionary, so you can avoid a System.Web dependency in your common code by depending on that abstraction:
Utility.dll
class Util
{
static void DoStuff(IDictionary environment) { ... }
}
App.dll
class App
{
void DoStuff()
{
Util.DoStuff(new Hashtable { { "Foo", "Bar" } });
}
}
Web.dll
class MyModule : IHttpModule
{
void Init(HttpApplication context)
{
Util.DoStuff(context.Context.Items);
}
}
Thanks to #user1429080. it is kind of simple DI pattern.
Add an interface to Util.dll.
Add a reference to it in class Util add a property to access it.
The interface is implemented in WebUtil.dll. WebUtil is referencing System.Web.
In HttpModule.Init() I assign the implementation to the interface.
Util class is using the interface to read data generated from HttpModule instead of accessing System.Web.
Now I can have another source of data by creating another implementation for the interface.

How to use Ninject in constructor injection of a type in an external assembly

I am loading a type from an external assembly and want to create an instance of the type. However, this type/class is setup for constructor injection by objects currently being managed/bound by Ninject. How can I use Ninject to create an instance of this type and inject any constructor dependencies?
Below is how I get this type.
Assembly myAssembly = Assembly.LoadFrom("MyAssembly.dll");
Type type = myAssembly.GetType("IMyType");
Assuming you've created a Kernel, you should be able to create and have it resolved via:
kernel.Get(type)
.... then I read the question.... Assuming MyAssembly.dll has an implementation of IMyType, you need (in your main assembly) :-
kernel.Load( "MyAssembly.dll")
And in your dynamically loaded assembly:-
public class Module : StandardModule
{
public override void Load()
{
Bind<IMyType>().To<MyType>();
}
}
And dont forget to see if MEF is the answer here, as you dont want to go writing reams of explicit plugin management and/or detection logic if you can help it (but if you're just doing straightforward stuff and are only doing the Assembly.LoadFrom() for the purposes of asking the question, you're probably still in Ninject's sweet spot.
Ditto, if you actually need to resolve an interface via Assembly.GetType(), you probably should be using something like dynamic to do the late binding you'll probably have to do (and before you know it you should be using a dynamic language or hosting a scriopting language)

how to call an dll file dynamically from code behind(.cs)

i have an microsoft .office.interop.excel(dll) located at an directory d:\abc. now i do not want to add them as an web reference in my projet and call them
rather call the dll dynamically from my code behind(.cs)
is ther any way we can do dynmically
anyhelp would be great
thank you
Yes, but you will need to use reflection because if you don't add the assembly as reference it won't be known at compile time. Take a look at LoadFrom method.
var assembly = Assembly.LoadFrom(#"d:\abc\microsoft.office.interop.excel.dll");
var someType = assembly.GetType("Namespace.Type");
var instance = Activator.CreateInstance(type);
someType.InvokeMember(... // the reflection pain goes on
Take a look in Assembly.Load() method.
I want to discourage you from doing that. It can definitely be done if read the dll into a byte[] and call AppDomain.CurrentDomain.Load(byte[]). However you will find that you can only work with the types of that assembly through reflection. Otherwise your code behind file will not compile. So if at all possible you should add a reference (not a web reference) to the dll.

Using external SWFs in a Flex application - duplicating MovieClip?

I'm working on an Flex application which uses many objects, e.g. LEDs, bulbs, gauges created in Flash. The objects internally consist of several small MovieClips and have their own logic inside. One of the initial requirements was that the objects have to be loaded at runtime, thus they were exported as SWF, not SWC. However, we ran into problem when we tried to duplicate loaded SWF. It turned out that MovieClip class doesn't have neither copying constructor nor method that would allow us to clone existing MovieClip. This way we'd end up loading an object every time from hdd, which involves a lot of overhead. Is it possible that language like ActionScript 3 doesn't have such a mechanism? Have we missed something out? If not, am I correct that the only solution is to use Flash Component Kit, make some custom components and include them as SWC at compile time?
After you load the MovieClip is it possible to use getDefinitionByName() as shown here?
http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#getDefinitionByName()
You are correct in that there is no built in way to duplicate a movieclip.
There are however work arounds. The esiest way as I see it is to give the movieclips classes.
You don't have to make the actual classes. Just write any name in the class field when setting up linkage on the top most movieclip that needs to be copied.
So a name for you LED movieclip, another name for the bulb etc.
The benifit is that now you have a class that you can initiate objects from.
No when you grap one of the movieclips you can duplicate it with the following method:
public function DuplicateDisplayObject(dO:DisplayObject):DisplayObject
{
if(dO == null)
return null;
var dOClass:Class = Object(dO).contructor;
return DisplayObject(new dOClass());
}
This assumes of cause that you can actually get a hold of one of the movieclips first. And mind you that it doesn't copy the state of the movieclip.
Another more importent note is that this only works if the you link the movieclips to classes. The classes doesn't have to exist (flash will create empty classes for you).
Other solutions could be:
Compiling against the classes without
including them (see the
"external-library-path" tag for the
flex compiler), and load the them at
runtime (from swf).
Compiling against the classes as a
RSL (Runtime Share Library) the swc
will be loaded at runtime.
Adobe has more info on how to do that, should be easy to find on their website.
A more exotic solution would be copy the bytecode of an object. Not sure if that would work with something on the displaylist, properly not.
About the solution using getDefinitionByName():
If I remember correctly you still need to give the movieclips fake classes, since getQualifiedClassName only returns MovieClip class. But I could be wrong.
Another solution:
private function duplicateImg(sourceLoaderInfo:LoaderInfo, target:Image):void
{
var ba:ByteArray = sourceLoaderInfo.bytes;
var dupCliploader:Loader = new Loader();
dupCliploader.contentLoaderInfo.addEventListener(
Event.COMPLETE, bytesLoaded);
dupCliploader.loadBytes(ba);
}
private function bytesLoaded(event:Event):void
{
var mc:MovieClip = event.currentTarget.content as MovieClip;
_img.source = mc;
_img.width = mc.width;
_img.height = mc.height+5;
}

Resources