I defined a custom attribute 'attribute' in a library 'Lib' that I use to annotate a method 'method' in a project 'Service'. However, when unit testing 'method' (in a distinct unit test project that holds a reference to 'Service' to depend on it), I am getting :
System.TypeLoadException: Could not load type 'attribute' from
assembly 'Lib'.
Why?
I tried adding a updated the dependency on 'Lib' of the unit test project, which solves the exception. However, I do not understand why it has to be updated, I thought the reference to 'attribute' could be encapsulated in 'Service' without requiring projects depending on 'Service' to upgrade 'Lib' version as well
Asked in a more abstract and generic way: is it possible to annotate the outermost layer of a code base (say, the HTTP api facade of a service), or will PostSharp annotations only work if the consumer of an API depends of the attribute class itself.
I am fairly new to C#, so I am not sure if this is a PostSharp feature, a c# dependency management feature, or a mix of both. Seems dependencies are not transitively resolved, but still, I don't expect the unit test project to directly depend on 'attribute', even though it calls a method annotated with it
Related
I'm trying to write an analyzer with codefix and I'm unsure on how I can
Add a required base class to the consumer project.
Preferred method would be to have it available at build time only (so generated)
Add the required dependency that this base class has to the consumer project so that compilation of the code fix does not fail. Maybe it's possible to check during analyze phase if that project has that dependency already installed?
The base class is needed by the generated code from the code fix and inherently the dependency of a 3rd party nuget.
I have a test which depends on both Moq and Castle.Core and trying to reference the interface Castle.DynamicProxy.IProxyTargetAccessor
The problem is that Moq embeds Castle.Core code within (all or part of it, not sure) and so Castle.DynamicProxy.IProxyTargetAccessor appears as public in both of these assemblies.
Now, I am creating a dynamic proxy explicitly using Castle.Core (cannot use the code embedded in Moq due to reduced visibility scope) and so the proxy implements the Castle.Core flavour of the interface.
Embarrassing, but I have no idea how to tell compiler to use the right interface or if it is at all possible.
EDIT 1
This is how the problem manifests itself in Rider:
But clicking any choice does nothing. Could be a Rider bug, because it would have to use some C# syntax to explicitly target the Castle.Core assembly. Not sure it exists, though.
I could rewrite the code using reflection, but I am curious if this has a compile time solution.
EDIT 2
Removing reference to Castle.Core does not work:
DynamicProxyFactory.cs(20, 26): [CS0122] 'ProxyGenerator' is inaccessible due to its protection level
DynamicProxyFactory.cs(27, 67): [CS0122] 'IInterceptor' is inaccessible due to its protection level
DynamicProxyFactory.cs(43, 38): [CS0122] 'IInterceptor' is inaccessible due to its protection level
DynamicProxyFactory.cs(91, 31): [CS0122] 'IInvocation' is inaccessible due to its protection level
This is because Moq does not really reference Castle.Core. Instead, it embeds it within with the help of ilmerge, probably. But apparently it modifies the visibility scope of certain interfaces that I want to use. Hence the compilation errors when using them.
EDIT 3
Courtesy of Reflector:
As one can see Castle.DynamicProxy.IInterceptor in the Moq is internal. While it is public in the latest version of Castle.Core.
So, I did not find how to reference a type from an assembly explicitly, but a comment by https://stackoverflow.com/users/5101046/scott-hannen helped me realize that I can upgrade Moq to the latest version where it no longer embeds Castle.Core, but references it normally.
That resolved my impediment.
I have a solution with several projects in it divided according to DDD principles. One of the integration tests wants to test one of the service method. The method has dependency on ICustomerRepository.
CustomerRepository is defined in CustomerDomain.Infrastructure assembly and the concrete ICustomerRepository is defined in CustomerDomain.Model assembly.
The dependency is managed by unity configuration file. The mapping is correct and it points out correct assemblies/namespaces and classes. The unity configuration file is copied correctly to the testresult folder. But, when the test runs it fails with the exception: "The type initializer for 'UnityContainerManager' threw an exception." containing inner exception :
"{"The type name or alias CustomerRepository could not be resolved. Please check your configuration file and verify this type name."}"
After some investigation I discovered that CustomerDomain.Model.dll is never copied to testResult dir even if the property Copy Local is set to True.
If I create an instance of CustomerRepository in TestInitialize method everything works - the assembly is copied and the test passes. But this workaround does seem right to me - is there any better option?
Visual Studio copies only those referenced assemblies of whom at least one type is used.
If you don't like to create the real CustomerRepository, define a dummy type CopyEnforcer in the referenced assembly and create an instance of that one in the referencing assembly.
TL:DR How do I reference an assembly only in a class library rather than both the library and the calling project?
I am building a utility library in C# in order to promote code reuse. In this instance, I am wanting to do something things with a TFS server and need to reference several assemblies from the TFS side of things:
Microsoft.TeamFoundation.Client
Microsoft.VersionControl.Client
Microsoft.WorkItemTracking.Client
I include these references in the class library called, say, Utility. I then proceed to wrap objects in those assemblies in helper objects. There are no errors, intellisense works correctly, and so forth.
When I want to use that class library in another project inside the same solution, say, TestCLI, I add a reference to the Utility project by selecting the project from the solution references tab. I can then use the Utility classes without issue, until I go to build.
When I build the solution, it throws an error such as:
The type 'Microsoft.TeamFoundation.VersionControl.Client.BranchObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.TeamFoundation.VersionControl.Client, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
In the past, I have worked around this issue by adding the same references to the calling project (TestCLI) in addition to the class library (Utility). I feel that this is defeating one of the purposes of having a class library and that I've missed a step in order to not have to worry about library references in my calling project.
Is there some way to resolve these dependencies without including the references in both the class library and the calling project? Am I structuring my solutions incorrectly? Am I thinking about class libraries in the incorrect manner?
The references are required because you are exposing objects from the other libraries, and then to use these classes the final program needs the references.
To avoid this you must hide the external objects, through a wrapper, a copy of the class or anything else, it depends primarily on what and why you are exposing those objects.
I have two projects that use the following Unity logic:
container.RegisterType<IUnitOfWork, MyDbContext>(
new HierarchicalLifetimeManager(),
new InjectionFactory(
c => new MyDbContext(configurationService.MySqlConnectionString)
)
);
container.RegisterType<DbContext, MyDbContext>(
new HierarchicalLifetimeManager()
);
The first project is a web application that utilises the Unity.MVC4 package so has a bespoke DependencyResolver doing some of the work - this works perfectly.
The second is a non-web application so uses a normal Unity package instance but errors when a call is made that uses MyDbContext. The exception is
System.Data.Entity.Core.MetadataException: Schema specified is not
valid. Errors: EntityDataModel.MyProject.ssdl(2,2) : error 0152: The
Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' for the 'System.Data.SqlClient'
ADO.NET provider could not be loaded. Make sure the provider assembly
is available to the running application. See
http://go.microsoft.com/fwlink/?LinkId=260882 for more information.
I've setup both projects to call the same service, which is in a separate project, in an attempt to isolate the source of the problem to the second project's Unity logic. I should also note I'm using Entity Framework 6 as the ORM.
My question is what Unity code do I need to get the second project to work, or is there some app.config entry I can add to reference the EF assemblies?
Update:
After some additional work I noticed that if I reference the DbContext assemblies:
EntityFramework
EntityFramework.SqlServer
in the second projects the problem disappears. I want to avoid referencing these assemblies because my client projects shouldn't have any knowledge of the ORM.
I've also tried updating the connection string so I'm manually specifying the ORM project's assembly (where my EDMX file is) as mentioned in this StackOverflow question but that hasn't made any difference.
metadata=res://nameOfDll/Model.csdl|res://nameOfDll/Model.ssdl|res://nameOfDll/Model.msl
You're doing it in the right way.
With DI you can remove dependencies from your application. So that you can get a "Repository agnostic" application. And you have effectively done it. At least on the projects that 'declare' the dependencies.
However, when the application has to run, you need to specify the concrete objects which will be used for the "declared" abstract dependencies (interface, abstract class) is required.
You do this by registering the types which object will be used for each abstract dependency. In you sample, when a IUnitOfWork or a DbContext, an instance of MyDbContext is provided.
So the projects that 'declare' the dependencies are completely independent of a particular implementation.
However, when you register the dependent types, you're loosing that independence.
Let's see it with an example:
If I say "I'm thirsty, I need to drink but I don't mind what I drink", I'm dependent on any drink, not on a particular one. But If I say "When I'm thirsty I want to drink coke" I'm dependent on coke.
The first part is the abstract definition of the dependency: "any drink" (like the abstract IUnitOfWork or DbContext). And the second part is the concrete dependency: "coke" (like MyDbContext).
So, I'm independent from coke as long as I don't specify that's what I want to drink. But once I say it, I'm dependent.
Perhaps what you're looking for is a way to change the repository at runtime. You can do it: don't register the dependencies in your code, because you need to make a reference to the project with the chosen concrete types. Do it in an external configuration (i.e. a file), so that you can compile your project without reference to the dependencies, and provide the required assemblies at runtime.
NOTE: When I say "declare" I mean using any of the patterns for injecting dependencies, like constructor injection (most advisabke) or any other injection pattern (property dependencies).