Note that this might be a duplicate of this question, I'm not entirely sure.
My problem is that I have a class library project which has a reference to a third-party type library (COM). I want to put contracts into the methods in the class library, like so:
public class foo
{
public static int divide(TypeFromTypeLib tftl, int a, int b)
{
Contract.Requires<ArgumentException>(b != 0);
return a / b;
}
}
And then have a client project make use of this method, e.g.
var n = foo.divide(null, 4, 2);
But I'd also like the client project also use contracts in some of its methods. So, I set the Code Contracts properties on both projects to 'Perform Runtime Contract Checking' (without which you get the runtime assert telling you that it needs this setting).
Now, when I then try to compile the client, I get the following error:
Could not resolve member reference: my_class_lib.foo::divide.
ccrewrite : error : Rewrite aborted due to metadata errors.
Which seems unavoidable - any time a method is called which has a type from the third party type library this happens. Remove the type from the method's signature and it's fine.
Can anyone explain why this happens? Is this a clue that the structure of my code is fundamentally flawed (if so, why?), or is it a quirk of code contracts? Is there a recommended fix for this problem?
To be honest I don't know why ccrewrite has a problem with interop types but I can give you 3 workarounds:
Solution 1
This one is the simplest:
Go to list of references for a project.
Find third-party type library.
Right click.
From the context menu select Properties.
Change Embed Interop Types from True to False.
You have to do that for both projects. The drawback of this solution is that after a build you will get an additional interop assembly in the bin folder.
Solution 2
Another solution might be to remove types from a third-party type library from a public interface i.e.:
public class foo
{
public static int divide(int a, int b)
{
return divide(null, a, b);
}
private static int divide(TypeFromTypeLib tftl, int a, int b)
{
Contract.Requires<ArgumentException>(b != 0);
return a / b;
}
}
Of course you can do that only if you do not need to use TypeFromTypeLib in your client.
Solution 3
If you need to use TypeFromTypeLib in your client you may write a wrapper for this class i.e.:
public class MyTypeFromTypeLib
{
//...
}
public class foo
{
public static int divide(MyTypeFromTypeLib mytftl, int a, int b)
{
var tftl = new TypeFromTypeLib();
//Map MyTypeFromTypeLib to TypeFromTypeLib
//...
return divide(tftl , a, b);
}
private static int divide(TypeFromTypeLib tftl, int a, int b)
{
Contract.Requires<ArgumentException>(b != 0);
return a / b;
}
}
However, this solution is cumbersome because additional classes are needed.
Related
I have been spending a lot of time trying to find a library that allows to log information about the methods that are being executed. Somehow I feel that all of them are too invasive. Is there any library or code that makes this so simple that I only need to add a decorator/attribute to the method?
Here what I would like to have:
internal class Calculator
{
[CustomInterceptor]
public static int Add(int a, int b)
{
return a + b;
}
}
internal class CustomInterceptor : Attribute
{
//here some implementation
}
static void Main(string[] args)
{
var result = Calculator.Add(10, 2);
Console.WriteLine($"Result : {result}");
}
Desired output
Before Add
Result 12
After Add
If this can be done with Reflection, please I would prefer that approach since that would imply no need for third party libraries.
Thanks in advance.
I have groups of logic that consist of static classes such as:
static class A {
static int mutate(int i) { /**implementation*/ };
static double prop(double a, double b) { /**implementation*/ };
}
static class B {
static int mutate(int i) { /**implementation*/ };
static double prop(double a, double b) { /**implementation*/ };
}
In this case, A and B are static classes that implement the same behavior via a group of functions (e.g. mutate). I would like to use something like an interface for this pattern, however since static classes cannot implement interfaces I am not sure what to do. What is the best way to implement this type of behavior cleanly?
EDIT:
Here is an example of what I am currently doing. The classes have no state so normally I would make them static.
Interface IMutator {
int mutate(int i);
}
class A : IMutator {
int mutate(int i) { /**implementation*/ };
}
class B : IMutator {
int mutate(int i) { /**implementation*/ };
}
class C {
public List<IMutator> Mutators;
public C(List<IMutator> mutators) {
Mutators = mutators;
}
}
//Somewhere else...
//The new keyword for A and B is what really bothers me in this case.
var Cinstance = new C(new List<IMutator>() {new A(), new B() /**...*/});
The stateless class doesn't have to be static.
Moreover, static dependencies isn't a good choice, when you want to write unit tests, or when you want to extract some common interface (as in your case).
It's OK to have non-static classes, containing logic only. E.g., people build ASP .NET applications using stateless controllers.
So, just throw away static and extract an interface.
Apart from #Dennis answer (which I have +1'ed, and it's indeed the way to go), other approach that may work, is having a set of functions (Func<>) and/or actions (Action<>) and resolve them using reflection. The code would not be specially elegant nor performant, but it works.
I've made a quick example on dotnetfiddle
I have some properties used to access fields from a parent class like so:
Class A:
private int _number = 42;
public virtual int Number { get { return _number; } }
Class B : A:
public override int Number { get { return base.Number + 1; } }
My question is, if I access B.Number, will it still resolve to a direct access to A._number (+ 1)?
This is assuming an optimized Release build, of course.
More importantly, are access modifiers abstract (as in they only matter when compiling and do not have an impact on code when running), or will they actually restrict access at runtime (other than when using Reflection, of course)?
Well they are abstract in the sense that they don't affect runtime performance but the information still needs to be stored in the compiled IL for cases where e.g security manager is enabled.
And no, the call to the getter function here wasn't inlined in x64 nor x86.
public static void Main(string[] args) {
B b = new B();
int a = b.Number;
}
You can use these instructions to disassemble the jitted code and see for yourself too.
I have a layered system of .dlls between my application, where the lowest level has a class that provides certain functionality - an instance of this class can be received through a GetClass() function and then I can access its properties (basically, a collection of information of changing objects).
Now I noticed that when I want to access that information from the next higher level .dll, the compiler complains that I do not have the lower level .dll referenced (the one defining the class) - which actually I would want to avoid, to have a nice layered structure in my architecture.
How to get around this? Can I re-expose the referenced type? Do I really have to write a wrapper of my own, if I want exactly the same functionality? Or do I even need to reference the low level .dll again?
DLL 1:
class myClass;
myClass GetMyClass();
DLL 2:
myClass GetMyClass();
EXE:
How to access result from calling GetMyClass (DLL 2) without referencing DLL 1?
You need to separate all the common classes you use across all your layers into a new dll, then reference this dll on every project.
Try to use interfaces so you can work over the contract (the functionality) instead of the concrete implementation. It will help you to avoid unnecessary references.
// common dll
public interface IMyClass
{
string MyData { get; set; }
IMyClass GetMyClass();
}
// dll1
public class myClass : IMyClass
{
public string MyData { get; set; }
public IMyClass GetMyClass() { return new myClass() { MyData = "abc" }; }
}
// dll2
public class myClass2
{
public IMyClass GetMyClass()
{
var c1 = new myClass();
var c2 = c1.GetMyClass();
return c2;
}
}
// exe (references common and dll2)
public class Program
{
public static void Main(string[] args)
{
var c1 = new myClass2();
IMyClass c2 = c1.GetMyClass();
Console.Writeline(c2.MyData);
}
}
Seems no way to achieve this, if myClass is defined in dll1, since objects of type myClass may be instantiated at runtime. To avoid this, you need to change the return type of GetMyClass() in dll2 to return something defined in dll2. It can be a class quite similar to myClass and having the same properties (you can even use tools like AutoMapper to easily convert between objects), but it definitely should be in dll2. Something like:
// dll1
class myClass
{
...
}
myClass GetMyClass()
{
...
}
// dll2
class myClass2
{
public myClass2(myClass c)
{
// instantiate myClass2 with values from myClass
}
}
myClass2 GetMyClass()
{
// somehow get myClass and convert it to myClass2 here
}
We do something similar to this in our local code. You can load the assembly at runtime, scan the types it contains using reflection, and again using reflection call functions and instantiate types from that dll, without ever referencing it directly in the project.
some of the key functions you will need are:
Assembly.LoadFrom(path); //get the assembly as a local object
Activator.CreateInstance(type); //create an instance of a type
Assembly.GetType(string);//fetch a type by name from the assembly
Once you have the type, basic reflection will give you pretty much every other piece you need.
Here is the snippet from my local code:
asm = Assembly.LoadFrom(Path.Combine(Environment.CurrentDirectory, filePath));
Type[] types = asm.GetTypes();
for (var x = 0; x < types.Length; x++)
{
var interfaces = types[x].GetInterfaces();
for (var y = 0; y < interfaces.Length; y++)
{
if (interfaces[y].Name.Equals("MyTypeName"))
{
isValidmod = true;
var p = (IMyType)Activator.CreateInstance(types[x]);
//Other stuff
}
}
Also note: this is pretty old code now. It has been neither reviewed nor refactored in years, so its essentially modern as of .NET 1.1, BUT: It illustrates the point. How to load a type from a remote assembly that is NOT locally referenced.
Additionally, this is part of an engine that loads some 50 of these, given a rigid folder structure, which is why its so generic looking. Take what you need from it.
The caller must have a reference to the class in DLL1 to know what type it is accessing. So yes you need to reference the first dll in the exe. Since GetMyClass() returns a type in DLL1 the type needs to be exposed in the exe, therefore dll1 must be referenced.
I go with Nick using any Ioc framework like spring.net or microsoft unity. to get the idea properly go through http://martinfowler.com/articles/injection.html
One solution here is to provide a 4th DLL that contains interfaces for your classes. You would reference this in all 3 of your layers, and return these interfaces instead of your classes.
This should give you a good idea of what I mean:
// DLL1
class ClassInDLL1 : IClassInDLL1
{
}
// DLL2
class ClassInDLL2
{
public IClassInDLL1 GetClassInDLL1()
{
return new ClassInDLL1();
}
}
// DLL3
class ClassInDLL3
{
public void DoSomething()
{
var dll2 = new ClassInDLL2();
var dll1 = dll2.GetClassInDLL1(); // dll1 variable is of type IClassInDLL1
// do stuff with dll1
}
}
// interface DLL
interface IClassInDLL1
{
}
I'll be honest though, layering your architecture like this is usually not an awesome idea unless your project is really large. I find that artificially making assembly splits like this ahead of time can cause you unnecessary pain, not to mention the fact that you end up with 3-4 assemblies for a medium or small project that might only need 1.
How would one pass a C# object via com? For example, say I have the following in a c# dll which is registered in the GAC and registry:
public int Add(int a, int b)
{
return a + b;
}
public int Add(NumberObject obj)
{
return obj.firstNumber + obj.SecondNumber;
}
How is it possible to make the NumberObject comvisible so that the client, who is going to use this, can set its values? A c++ example would be great, is it even possible? Or are only native types like int, string etc passable by COM?
a good tutorial.