Agatha RRSL and StructureMap 3.0 - structuremap

I want to use Agatha RRSL with my implementation of the StructureMap 3.0 wrapper to Agatha's IoC container. Agatha has NuGet packages with StructureMap 2.6 which I do not like.
I started by copy/pasting the code from Agatha.StructureMap source code and proceeded to make the changes to use 3.0 StructureMap.
The issue I now have is that I get a StructureMapException
StructureMap.StructureMapBuildPlanException occurred
_HResult=-2146233088
_message=Unable to create a build plan for concrete type Agatha.Common.WCF.RequestProcessorProxy
HResult=-2146233088
IsTransient=false
Message=Unable to create a build plan for concrete type Agatha.Common.WCF.RequestProcessorProxy
new RequestProcessorProxy(InstanceContext, String endpointConfigurationName, String remoteAddress)
┗ InstanceContext = **Default**
String endpointConfigurationName = Required primitive dependency is not explicitly defined
String remoteAddress = Required primitive dependency is not explicitly defined
Source=StructureMap
Context=new RequestProcessorProxy(InstanceContext, String endpointConfigurationName, String remoteAddress)
┗ InstanceContext = **Default**
String endpointConfigurationName = Required primitive dependency is not explicitly defined
String remoteAddress = Required primitive dependency is not explicitly defined
Title=Unable to create a build plan for concrete type Agatha.Common.WCF.RequestProcessorProxy
StackTrace:
at StructureMap.Pipeline.ConstructorInstance`1.ToBuilder(Type pluginType, Policies policies) in c:\BuildAgent\work\996e173a8ceccdca\src\StructureMap\Pipeline\ConstructorInstance.cs:line 83
InnerException:
This looks to me as though the constructor StructureMap thinks it needs to use, but views as not properly configured, is the one with multiple parameters. In reality I need it to use the parameterless constructor.
However I think I've configured the constructor properly. Here is the code I use to configure a parameterless constructor for RequestProcessorProxy:
structureMapContainer.Configure(x => x.ForConcreteType<RequestProcessorProxy>().Configure.SelectConstructor(() => new RequestProcessorProxy()));
What may have gone wrong?
Just as heads up, I'm new to both StructureMap and Agatha so I may have misunderstood any or all of the above...

I've never used SelectConstructor so don't know how to make it working with it but if you want to make SM to use parameterless constructor then you can do it like this when you resolve concrete type:
var container =
new Container(
c => c.For<RequestProcessorProxy>().Use(() => new RequestProcessorProxy()));
or like this when you are resolving it by the interface:
var container =
new Container(
c => c.For<IRequestProcessor>().Use(() => new RequestProcessorProxy()));
I am not familiar with Agatha RRSL at all so I don't know whether I used good interface.
Hope this helps!

Related

StructureMap and Proto.Actor in .NET Core 2

I have been using Proto.Actor and specifically the ActorFactory to spawn actors. To be able to use these features I need to add services.AddProtoActor() to the ConfigureServices method of my startup class.
However, now I want to transition to using StructureMap as my IoC container, but the two do not appear to play nicely together - when I add the following code from guides I have found online:
public IServiceProvider ConfigureIoC(IServiceCollection services)
{
// static class method that scans assemblies
IContainer container = IocContainer.SetupContainer();
container.Configure(config =>
{
config.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
When it tries to run config.Populate I get the following error:
System.ArgumentOutOfRangeException: Specified argument was out of the
range of valid values. Parameter name: EventStream must have at
least one public constructor to be plugged in by StructureMap
Does anyone have any ideas how to get the IActorFactory created correctly as a singleton in StructureMap (or have a workaround)?
In the end, using StructureMap removes the need I had for the ActorFactory itself. So instead of getting the actor's PID from the factory I have two lines:
var props = Actor.FromProducer(() => container.GetInstance<MyActorType>());
var pid = Actor.Spawn(props);

How to convert C# code that uses Shell COM to F#?

I have the following C# method:
private static bool IsLink(string shortcutFilename)
{
var pathOnly = Path.GetDirectoryName(shortcutFilename);
var filenameOnly = Path.GetFileName(shortcutFilename);
var shell = new Shell32.Shell();
var folder = shell.NameSpace(pathOnly);
var folderItem = folder.ParseName(filenameOnly);
return folderItem != null && folderItem.IsLink;
}
I have tried converting this to F# as:
let private isLink filename =
let pathOnly = Path.GetDirectoryName(filename)
let filenameOnly = Path.GetFileName(filename)
let shell = new Shell32.Shell()
let folder = shell.NameSpace(pathOnly)
let folderItem = folder.ParseName(filenameOnly)
folderItem <> null && folderItem.IsLink
It however reports an error for the let shell = new Shell32.Shell() line, saying that new cannot be used on interface types.
Have I just made a silly syntactic mistake, or is there extra work needed to access COM from F#?
I don't know enough about the F# compiler but your comments makes it obvious enough. The C# and VB.NET compilers have a fair amount of explicit support for COM built-in. Note that your statement uses the new operator on an interface type, Shell32.Shell in the interop library looks like this:
[ComImport]
[Guid("286E6F1B-7113-4355-9562-96B7E9D64C54")]
[CoClass(typeof(ShellClass))]
public interface Shell : IShellDispatch6 {}
IShellDispatch6 is the real interface type, you can also see the IShellDispatch through IShellDispatch5 interfaces. That's versioning across the past 20 years at work, COM interface definitions are immutable since changing them almost always causes an undiagnosable hard crash at runtime.
The [CoClass] attribute is the important one for this story, that's what the C# compiler goes looking for you use new on a [ComImport] interface type. Tells it to create the object by creating an instance of Shell32.ShellClass instance and obtain the Shell interface. What the F# compiler doesn't do.
ShellClass is a fake class, it is auto-generated by the type library importer. COM never exposes concrete classes, it uses a hyper-pure interface-based programming paradigm. Objects are always created by an object factory, CoCreateInstance() is the workhorse for that. Itself a convenience function, the real work is done by the universal IClassFactory interface, hyper-pure style. Every COM coclass implements its CreateInstance() method.
The type library importer makes ShellClass look like this:
[ComImport]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("13709620-C279-11CE-A49E-444553540000")]
public class ShellClass : IShellDispatch6, Shell {
// Methods
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x60040000)]
public virtual extern void AddToRecent([In, MarshalAs(UnmanagedType.Struct)] object varFile, [In, Optional, MarshalAs(UnmanagedType.BStr)] string bstrCategory);
// Etc, many more methods...
}
Lots of fire and movement, none of it should ever be used. The only thing that really matters is the [Guid] attribute, that provides the CLSID that CoCreateInstance() needs. It also needs the IID, the [Guid] of the interface, provided by the interface declaration.
So the workaround in F# is to create the Shell32.ShellClass object, just like the C# compiler does implicitly. While technically you can keep the reference in a ShellClass variable, you should strongly favor the interface type instead. The COM way, the pure way, it avoids this kind of problem. Ultimately it is the CLR that gets the job done, it recognizes the [ClassInterface] attribute on the ShellClass class declaration in its new operator implementation. The more explicit way in .NET is to use Type.GetTypeFromCLSID() and Activator.CreateInstance(), handy when you only have the Guid of the coclass.

No default instance or named instance 'Default' for requested plugin type

I'm trying to avoid referencing the concrete type library in my main project, but I'm getting this error:
No default instance or named instance 'Default' for requested plugin type StackExchangeChatInterfaces.IClient
1.) Container.GetInstance(StackExchangeChatInterfaces.IClient ,{username=; password=; defaultRoomUrl=; System.Action`2[System.Object,System.Object]=System.Action`2[System.Object,System.Object]})
I've setup my container to scan for assemblies, like so:
var container = new Container(x =>
{
x.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.ExcludeNamespace("StructureMap");
scan.WithDefaultConventions();
scan.AddAllTypesOf<IMessageHandlers>();
});
//x.For<IClient>().Use<Client>(); //GetInstance will work if this line is not commented out.
});
When I try to get an instance, I get the error, my code for getting an instance is here:
chatInterface = container
.With("username").EqualTo(username)
.With("password").EqualTo(password)
.With("defaultRoomUrl").EqualTo(roomUrl)
.With<Action<object, object>>(delegate(object sender, object messageWrapper)
{
string message = ((dynamic)messageWrapper).Message;
Console.WriteLine("");
Console.WriteLine(message);
foreach (var item in messageHandlers)
{
item.MessageHandler.Invoke(message, chatInterface);
}
}).GetInstance<IClient>();
If I explicitly map the concrete class to the interface, everything works hunky dory, but that means I need to reference the project that Client is in, which I don't want to do.
This is really interesting. Looks like default conventions are not able to register types with such constructor (tried on both versions 2.6.3 and 3+). I was only registered when only parameterless constructor was specified. Looking at sources of both versions it is really suspicious as it should be registered. Deeper dive into the code would be needed...
Anyway try using custom registration convention:
public class ClientConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.IsClass && !type.IsAbstract && !type.IsGenericType &&
type.GetInterfaces().Contains(typeof(IClient)))
{
registry.For(typeof(IClient)).Use(type);
}
}
}
Configure it like this:
var container = new Container(
c => c.Scan(
s =>
{
s.ExcludeNamespace("StructureMap");
s.WithDefaultConventions();
s.Convention<ClientConvention>();
s.AddAllTypesOf<IMessageHandlers>();
}));
and this should work just fine.
The default type scanning will not pick up concrete types whose constructor functions contain primitive arguments like strings, numbers, or dates. The thinking is that you'd effectively have to explicitly configure those inline dependencies anyway.
"but that means I need to reference the project that Client is in, which I don't want to do."
Does that actually matter? I think you're making things harder than they have to be by trying to eliminate the assembly reference.

Simple Injector manually registering controllers

I'm attempting to implement Dependency Injection into my architecture (MVC, DDD - Domain Model, Repository). And my architecture includes ASP.NET Identity 2.0.
At this stage, I don't want DI controlling any of the Identity 2.0 objects (UserAdminController, RolesAdminController...). I'd prefer the security objects outside of DI. At this stage, integrating the Identity objects in DI looks very difficult. I had a good look to see if someone has already done this, so I could read and learn how to do this. I couldn't find anything. (Found one post which came close, but no resolution).
Anyway, I've followed the Simple Injector MVC implementation (see standard code below), and trying many things, I believe the problem lies in me calling RegisterMvcControllers.
Correct me if I'm wrong, but this statement will pickup all controllers with their name post-fixed with "controller".
Question: How can I select which controllers get registered with Simple Injector? (Is this called manually registering?)
Any help would be greatly appreciated, as I've spent most of today trying to get my head around all this, and proceed to the next step, i.e. have DI implemented, and instantiating my objects.
...
...
... called from Application_Start()
// Create a Simple Injector container
var container = new Container();
// Configure the container
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
// Verify the container's configuration
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
private static void InitializeContainer(Container container)
{
container.Register<MyService1>();
container.Register<IMyRepositoryA, MyRepositoryA>();
// Trying to include Identity into Simple Injector - please ignore
container.Register<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(new ApplicationDbContext()));
}
The RegisterMvcControllers has the following constraints on the types it registers:
The type must be public
The type must implement System.Web.Mvc.IController
The type must not be abstract
The type must not be a generic type definition
Its name must end with "Controller"
You can see what happens here in the source code.
The RegisterMvcControllers extension method calls into the SimpleInjectorMvcExtensions.GetControllerTypesToRegister method to get the list of controllers to register. You can call that method yourself to see what is registered as follows:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
So instead of calling RegisterMvcControllers you can register the controllers yourself by calling the GetControllerTypesToRegister method:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly());
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
This way you can filter out any controller you want to register manually:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
.Where(type => type.Name != "UserStore`1");
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
Another option is to override the registration:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Options.AllowOverridingRegistrations = true;
container.Register<IUserStore<ApplicationUser>>(
() => new UserStore<ApplicationUser>(new ApplicationDbContext()))
// Always set the option back to false ASAP to prevent configuration errors.
container.Options.AllowOverridingRegistrations = false;

Autofac error: The instance registration can support SingleInstance() sharing only

When I try to register my class with autofac I get the following error: "The instance registration 'GetAllDivisionsCommand' can support SingleInstance() sharing only".
I don't understand why I'm getting this error, but assume it's something to do with the class having static member variables used for caching as that's the only thing that's different about this class. I haven't had any trouble registering any other classes as either SingleInstance or InstancePerDependency.
Essentially, the class is used to retrieve a rarely changing list of divisions from the database, and caches the result. Each time the command is run, it first checks for changes on the database and then re-runs the query if changes are detected; if not, it returns the cached list.
So I am trying to register GetAllDivisionsCommand with Autofac as an IGetAllDivisionsCommand. IGetAllDivisionsCommand itself implements IInjectableCommand, which is just a marker interface, and ICachedListCommand. The concrete command class inherits from the abstract base class CachedListCommand which is where the static member variables live.
Does anyone know what would cause this error message? SingleInstance won't work for me as I can't keep reusing the same session.
Code:
Type commandType = typeof(IInjectedCommand);
Type aCommandType = typeof(GetAllDivisions);
var commands =
from t in aCommandType.Assembly.GetExportedTypes()
where t.Namespace == aCommandType.Namespace
&& t.IsClass
&& !t.IsAbstract
&& (commandType.IsAssignableFrom(t))
let iface = t.GetInterfaces().FirstOrDefault(x => "I" + t.Name == x.Name)
select new { Command = t, Interface = iface };
foreach (var cmd in commands)
{
builder.RegisterInstance(cmd.Command).As(cmd.Interface).InstancePerLifetimeScope();
}
RegisterInstace as the name implies is for registering instances not types.
What you need is RegisterType:
foreach (var cmd in commands)
{
builder.RegisterType(cmd.Command).As(cmd.Interface).InstancePerLifetimeScope();
}
And by the way with the Autofac scanning feature your registration code is roughly equivalent:
builder
.RegisterAssemblyTypes(aCommandType.Assembly)
.AssignableTo<IInjectedCommand>()
.InNamespace(aCommandType.Namespace)
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
In my case, I did want RegisterInstance because I actually have an instance in hand that I wanted to register.
I had
builder.RegisterInstance(myInstance).InstancePerDependency();
The documentation for InstancePerDependency reads:
Configure the component so that every dependent component or call to
Resolve() gets a new, unique instance (default.)
On closer inspection, it makes sense that registering an instance with "instance per dependency" is not possible, since it is not possible for Autofac to give back a new instance each time Resolve is called if there is in fact 1 instance registered.
So, in my case, the solution was this.
builder.RegisterInstance(myInstance).SingleInstance();
The Autofac exception could possibly have been worded more clearly to explain this problem.

Resources