I have registered a generic type in a Unity config file. It works, but ReSharper flags this syntax in red as an INCORRECT_TYPE_PARAMETER_NUMBER error. Is there a way to do this that will keep ReSharper happy, without adding overhead to the config file?
<unity>
<type alias="IList`1" type="System.Collections.Generic.IList`1, mscorlib"/>
^^^^^^^
<type alias="List`1" type="System.Collections.Generic.List`1, mscorlib"/>
^^^^^^
<type alias="string" type="System.String, mscorlib"/>
<type alias="int" type="System.Int32, mscorlib"/>
<register type="IList`1[string]" mapTo="List`1[string], mscorlib"/>
<register type="IList`1[int]" mapTo="List`1[int], mscorlib"/>
</unity>
Have you tried using the full assembly name for mscorlib (including the assembly version, public key token, etc.)?
Related
All I want to do is (in an app.config) define a singleton 'Int32'. The idea is that it will be a named registration, and used as a parameter in multiple other type definitions - meaning the actual int value itself only needs to be defined once (and reducing manual error).
Something along the lines of the following...
<register type="int" name="MyInt">
<lifetime type="singleton" />
<constructor>
<param name="value" value="23"/>
</constructor>
</register>
Now I realise the Int32 structure doesn't have such a constructor, but what I am requesting seems so simple that I cant believe it cant be done.
Am I missing something obvious?
Cheers!
You should be able to specify a single instance:
<container>
<instance name="FooBar" type="System.Int32" value="123" />
</container>
Which is resolved like so:
int value = container.Resolve<int>("FooBar");
If you would require to construct another type from configuration, it would be like so:
<!-- "SomeType" is a type here, but you can have any mapping here -->
<register type="SomeType">
<constructor>
<!-- "value" is the name of the constructor argument -->
<param name="value" dependencyName="FooBar" />
</constructor>
</register>
Can you change behavior from Dependency injection to reading config file?
Here good example how you can put int value to config file and read it without DI.
Second solution: you can wrap your int value into simple object with singl property and necessary constructor.
I need to generate the shims through Microsoft Fakes Platform for three sealed classes of external managed assembly. I wrote this:
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
<Assembly Name="acmgd" Version="17.2.0.0"/>
<StubGeneration>
<Clear/>
</StubGeneration>
<ShimGeneration>
<Clear />
<Add FullName=
"Autodesk.AutoCAD.ApplicationServices.Application"/>
<Add FullName=
"Autodesk.AutoCAD.ApplicationServices.DocumentCollection"/>
<Add FullName=
"Autodesk.AutoCAD.ApplicationServices.Document"/>
</ShimGeneration>
</Fakes>
The each of these classes is sealed. The Microsoft Fakes Platform doesn't create the shim for Autodesk.AutoCAD.ApplicationServices.Application (the ShimApplication class is not exist in the result):
The type or namespace name ShimApplication does not exist in the
namespace Autodesk.AutoCAD.ApplicationServices.Fakes (are you
missing an assembly reference?)
I haven't this problem for other two types. How can I fix it?
Also I have a question about the fakes-file structure. I can't find info about the ShimGeneration element. In the MSDN samples I see the StubGeneration element using only. From MSDN:
Stubbing concrete classes and virtual methods
By default, stub types are generated for all non-sealed classes. It is
possible to restrict the stub types to abstract classes through the
.fakes configuration file:
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
<Assembly Name="mscorlib" />
<!-- user code -->
<StubGeneration>
<Types>
<Clear />
<Add AbstractClasses="true"/>
</Types>
</StubGeneration>
<!-- /user code -->
</Fakes>
But in real life the XSD schema doesn't define the Types and the Add hasn't AbstractClasses attribute...
Where can I find actual and detailed info about the fakes-format?
If I have a class that implements a generic interface it works fine to configure it using the unity xml config.
public interface IReader<T> { }
public class Fund { }
public class FundReader : IReader<Fund> { }
and the unity xml:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<namespace name="System.ComponentModel" />
<namespace name="TestUnityIssue" />
<assembly name="TestUnityIssue" />
<container>
<register type="IReader[Fund]" mapTo="FundReader" />
</container>
</unity>
And this works just using the following code:
var container = new UnityContainer().LoadConfiguration();
var fundReader = container.Resolve<IReader<Fund>>();
However, in some cases there is a wrapper around the type used in the reader. For example, adding the following two classes:
public class Wrapper<T> { }
public class WrappedFundReader : IReader<Wrapper<Fund>> { }
and if I add the following to the unity config:
<register type="IReader[Wrapper[Fund]]" mapTo="WrappedFundReader" />
and then try to resolve it using:
var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();
I get the following exception:
InvalidOperationException - The current type,
TestUnityIssue.IReader`1[TestUnityIssue.Wrapper`1[TestUnityIssue.Fund]],
is an interface and cannot be constructed. Are you missing a type
mapping?
I can get around this by configuring it using code instead of xml:
container.RegisterType<IReader<Wrapper<Fund>>, WrappedFundReader>();
or I can create an interface that goes between and use that instead:
public interface IWrappedReader<T> : IReader<Wrapper<T>> { }
public class WrappedFundReader : IWrappedReader<Fund>
and the config would change to:
<register type="IWrappedReader[Fund]" mapTo="WrappedFundReader" />
It will still give me an instance that I can cast to IReader<Wrapper<Fund>>, but it seems like I should be able to make this work with the unity config.
What am I missing to make this work?
(If also tried creating specific aliases and wasn't able to get that to work either)
Aliasing worked for me...
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], TestUnityIssue, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<namespace name="TestUnityIssue" />
<assembly name="TestUnityIssue" />
<container>
<register type="IReader[Fund]" mapTo="FundReader" />
<register type="IReader[WrappedFund]" mapTo="WrappedFundReader" />
</container>
</unity>
these both resolved...
var fundReader = container.Resolve<IReader<Fund>>();
var wrappedReader = container.Resolve<IReader<Wrapper<Fund>>>();
and depending on your situation, you may be able to get away with less than the full AssemblyQualifiedName...
<alias alias="WrappedFund" type="TestUnityIssue.Wrapper`1[[TestUnityIssue.Fund, TestUnityIssue]], TestUnityIssue" />
I have code that register two classes with the same names and namespaces but from different assemblies. Here's how I resolve this problem using Unity config file:
<register type="IMyService" mapTo="CoordinatingMyService" />
<register type="IMyService" mapTo="MyNamespace.MyService, MyService.Version1" name="V1"/>
<register type="IMyService" mapTo="MyNamespace.MyService, MyService.Version2" name="V2"/>
My question is how I can achieve the same in code instead of the config file.
Currently I am trying to use a config file to give Unity Framework information that looks like this...
<configuration>
<unity>
<typeAliases>
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Culture=neutral, Version=1.1.0.0, PublicKeyToken=31bf3856ad364e35" />
</typeAliases>
<containers>
<container>
<types>
<type type="Common.ISharedConfiguration, Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=1111111111111111" mapTo="Common.SharedConfigurationManager, Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=1111111111111111">
<lifetime type="singleton" />
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<constructor>
<param name="OurEnumChoice" parameterType="MyProjectsEnum" >
<value value="MyProjectsEnum.OurFirstConstant" type="MyProjectsEnum"/>
</param>
</constructor>
</typeConfig>
</type>
</types>
</container>
</containers>
</unity>
</configuration>
If I choose something like System.String and have my concrete class have a construtor of string this config file info for Unity works great. The moment I choose to use an Enum instead of string Unity throws an error like this...
Could not load type MyProjectsEnum from assembly Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf33856ad364e35
I think I need an understanding of what I can pass as an understood type by Unity beyond simple types through this configuration process.
You need to specify fully qualified type name for both 'parameterType' and 'type' attributes. Much the same you did for 'typeAlias' node. By default, Unity looks up its own assembly for unqualified types.