C# class libary - targetting .NET2 framework.
I'm trying to implement a public interface (exposed from a second referenced assembly) in a small class. The interface has only 3 methods: one is fine, but for some reason I can't implement the other two of them without the compiler complaining for each one that:
my class "does not implement InterFaceName.MethodName"
"InterFaceName.MethodName in explicit interface declaration is not a member of interface".
The only difference between the one method which compiles and the other two is that the problem methods each have a parameter which is an Office Interop (Word) type. The other parameters are either bool or members of other public interfaces.
I can add my class definition here if it helps, but I would need to do some paraphrasing since I'm not the "owner" of the other assembly (it is a commercial product) and I'm not sure how they'd feel about me "exposing" it...
That's kind of vague I know, but I'm hoping someone's run into this kind of error before.
Thanks for any pointers.
This can often happen if the referenced assembly is built against a different version of the Office Interop assemblies.
As a result, even though visibly the parameters declared for "MethodName" may appear to match the interface from the referenced assembly, since the assembly versions are different, the method declaration does not actually match the decleration from the referenced assembly.
Double check you are using the exact same version of the interop assemblies.
Related
In my project, there is an abstract base class with an abstract method.
We generate implementations based on a schema and later load these by reflection with Assembly.LoadFrom and then call Assembly.GetType to get a concrete implementation of an interface which is defined in yet another DLL.
The structure of the different projects (DLL files):
Schema - Containing type definition
Base - Has the base class shared by all generated implementations
Generated - A generated type that implements the abstract base class from Base and the interface from Schema.
public interface IExample
{
//Some methods here, irrelevant to the problem
}
public abstract Base
{
protected abstract void SomeMethod(SomeType someArg); //This method is the method the exception specifies, but I suspect it's only because it's the first one in the file.
//More methods like the above, and some non-abstract/virtual methods too
}
public class Generated : Base, IExample
{
protected override void SomeMethod(SomeType someArg)
{
//Some implementation here
}
//More content here, not all of it being from either the interface or the Base type
}
var asm = Assembly.LoadFrom(path);
asm.GetType("SomeNameSpace.Generated"); //This is where it fails
This worked fine until the Base project was updated in an unrelated area and its version advanced.
The generated implementation is being requested by the interface type it implements. (Generics are involved in the type definition, not sure if that's really relevant)
Now normally this would be a simple case of "Oh you just need to re-compile it and include it again" but the exciting part is that this only sometimes fails!
Roughly half the time, it just works. The other half, it throws the TypeLoadException arguing the method doesn't have an implementation.
Normally I'd expect it to always fail, but that's not the case.
Of course, including the newly compiled Generated DLL avoids this entirely. But I'm looking to be able to update both the Schema and Base projects without requiring the whole thing. (It's for 'service pack' style software updates only containing the relevant files)
Just to be clear, none of the involved types were modified. No "Oh I just added an optional argument to a method so it's the same method" mistakes.
The only changes are in other parts of the files. Base is in a big DLL with lots of unrelated utility in it. Base, IExample, and the resulting Generated are still exactly the same. If it was some version resolution causing havoc, I'd expect problems.
This is sadly not a simple small project I could pack up into a reproducible example, but a rather complicated program with many layers and patterns. I'm not sure I could reproduce this if I tried, I'm relying on it failing when the program starts loading things and calling code. (The relevant reflection code that creates an instance of Generated)
The exception message looks like this: (names changed to match example code, and yes its assembly version is 0.0.0.0)
System.TypeLoadException: Method 'SomeMethod' in type 'SomeNameSpace.Generated' from assembly 'SomeNameSpace.Generated, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
at SomeMoreOfOurOwn.CallingTheReflection.AndFailing(Factory factory)
As mentioned, this is a case where trying the same thing and hoping for different results works, because this issue doesn't happen half the time. (And not due to the code not being called, the codebase is built on this pattern for everything)
The only predictable thing is that it always fails on the same thing, but I think that's just because it's deterministically doing that one thing first amongst all of the non-updated generated files.
This is a .NET Framework 4.7.1 project.
We found one suspect. Apparently the fact we also load a DLL used by Base's DLL by reflection via AssemblyResolve it might cause this issue when there's a version mismatch because it's also directly referenced by another directly referenced assembly, and the Generated DLL, who is also loaded using Assembly.LoadFrom. (Using Assembly.Load instead had no effect by the way.)
We've only got tentative proof of this being the matter, but it's the best hunch we've got.
So in conclusion, avoid doing whatever it is we're doing in our project.
I have this as the main class of my dll:
namespace PTEmu
{
public class DatabaseProtocol : IDatabaseProtocol
{
(constructors and methods)
}
}
This code I use to Load the DLL and create an instance of the class
var assembly = Assembly.LoadFrom("database\\" + file);
var t = assembly.GetType("PTEmu.DatabaseProtocol");
var protocol = Activator.CreateInstance(t) as IDatabaseProtocol;
Assembly.LoadFrom, assembly.GetType and Activator.CreateInstance itself, doesn't throw any errors.
I can't see what is wrong, sice I took this piece of code from another project that worked fine with it.
If I remove as IDatabaseProtocol, it returns an object, but not an object like the interface I want, so I can call the methods easily...
This is a problem of type identity. The identity of a type in .NET is not just the namespace name and type name. It also includes the assembly from which it came. So the mistake here is that you had two distinct interface types. One that came from your main assembly, another that came from the plugin assembly. Adding the source code file with Add Link isn't good enough, it matters which assembly the type got compiled into. Or in other words, the source code file plays no role at all in the type identity.
Notable perhaps is that this rule was changed in .NET 4. The identity of a type can be the solely determined by the value of the [Guid] attribute applied to the type. This enabled the "Embed Interop Types" feature in the properties of an assembly reference. Also known as the No PIA feature. It is however only valid on COM interface types. It put an end to having to install massive PIAs when you write code that automates Office apps.
You'll however have to do the exact equivalent of a PIA, a third assembly that defines the interface type and is referenced by both projects.
I solved my problem by adding a new project named framework that stores the interface. Then I referenced it in my two other projects.
Don't bother and don't waste your time!
Create a new DIFFERENT class library for interfaces
Create an interface in this new library
implement the interface in your class (other project)
try to re-run
TAADAAAM!!!
.net need this interface to be in OTHER class library and not the same one!!
I had almost similar issue. But in my case the interface was already in a different shared class library.
Solution was to set the "Copy Local" property for the shared reference project to "No".
I've got a .dll library I'm writing that interfaces with a proprietary COM assembly. My goal is to publish my work online once it's built, however I need to remove the COM assembly as a project reference to avoid distribution of this proprietary dll. So what I'm trying to be able to do is dynamically load the assembly at runtime, and invoke methods where I need them. Traditionally I've used object reflection for unknown types, however this can get slow at times, and involves several ugly instanciations. In .NET 4.0 is there a way to cleanly get all the methods and toss them into a dynamic class/interface at runtime?
I'm currently getting the object like this:
Type myClassType = Type.GetTypeFromProgID("MyClass.Myclass.1");
object classObj = Activator.CreateInstance(myClassType);
I thought I'd be able to use Type.GetMethods(), however it only returns the generic ones (Equals, ToString, GetLifetime..., etc.). I know the class uses an interface, so I tried looking into dynamically loading the interface also. That led me to Reflection.Emit, and the Microsoft.Xrm.Sdk, which I am failing to understand so far.
If there's a way for me to invoke methods without needing to throw a bunch of BindingFlags every few lines, I'd greatly appreciate a nudge in the right direction
I do have the GUID for both the Class and the Interface if that helps at all.
If I were at your situation(and if i have understand the problem correctly):
I would separate the Interface,s library (DLL) from implementation library(DLL)
Then the implementation library would be loaded dynamically and my main source code that is
referenced to Interface library would be complied
Type myClassType = Type.GetTypeFromProgID("MyClass.Myclass.1");
myClassIntrface classObj =
Activator.CreateInstance(myClassType) as myClassIntrface;
classObj.CallSomeInterfaceMethod();
hope this will be useful pal.
is it possible to use an interface type, that is defined in a huge external dll, without referencing that dll?
in other words, there will be one core or global dll, that references the external dll, and all the projects reference this global one, so the external dlls are hidden from the other projects.
I want to use the type in my code, while knowing only about the global AllInterfaces project.
can that work? and if so, what needs to be done for such a scenario?
Is it possible to use an interface type that is defined in a huge external dll, without referencing that dll at compile time?
Not really, no. The compiler has the reasonable expectation that the types it needs are available.
Is it possible to use an interface type that is defined in a huge external dll, without referencing that dll at runtime?
Yes. We added that feature to C# 4. The "proper" name for the feature is something like "Type Embedding with Type Equivalence", but everyone just calls it "No PIA".
The motivation for the feature is the one faced most obviously by Visual Studio Tools For Office developers. VSTO developers write C# code that customizes, say, an Excel spreadsheet with some managed code. They communicate with Excel via a managed interface, but of course Excel actually exposes a set of COM interfaces. To bridge that gap, the Office team supplies a Primary Interop Assembly, or PIA. The PIA is a huge external library that contains nothing but metadata that describes how the managed interfaces correspond to the unmanaged interfaces of the COM objects.
The problem is that the Office team does not by default install the PIA when your customer buys Office! Therefore you have to ship the PIA with your customization. And the PIA is so large, it is often many times the size of the customization, which makes your download longer. And so on; it's not an ideal situation by any means.
The No-PIA feature allows the compiler to link only the portions of the PIA you actually use into your library, so that you do not have to ship the PIA with it.
Now, you might ask "what if I have two customizations that communicate with each other, and both use the IFoo interface from a PIA that I am not shipping?" The runtime identifies types by the assembly they came from, and so the two IFoo interfaces would be considered different types, and therefore not compatible.
The "No PIA" feature takes this into account as well. It does the same trick you use in COM to solve this problem: the assembly instructs the runtime to unify all interfaces that have the same GUID into the same logical type even if they come from different assemblies. This thereby explains the requirement that every interface that you use with "no PIA" has to be marked as though it were a COM interop interface with a GUID.
On the command line, use /L instead of /R to reference an assembly as a "no PIA" assembly.
Do a web search on "no PIA" and you'll find more information on this feature.
If you want to use that interface type in your code, that interface should be visible to your code. You code won't compile.
You can write adapter interface in your global dll, for the original interface and use that every where.
It cannot be done statically but you can do it using reflection.
With C# 4 you can use the dynamic keyword.
However, I fail to see how not knowing the interface in advance is going to help you - how are you going to know which methods to call?
You are trying to fool type identity. The CLR identifies a type by these properties:
Assembly display name
[AssemblyVersion]
[AssemblyCulture]
The assembly's PublicKeyToken value
The assembly's processor architecture (implicit)
The type's namespace name
The type's name.
Faking the type namespace name and name isn't difficult, the hard thing to do is faking the assembly properties. You are dead in the water if the assembly is strong-named (non-null PublicKeyToken) or if it is stored in the GAC, you can't get the substitute loaded. Faking the culture and architecture isn't hard to do, you'll have to get the display name and version right.
And of course, you'll have to get the interface declaration exactly right. Intentionally invoking DLL Hell like this is otherwise an Extremely Bad Idea. Not in the least because you now can never get the real assembly loaded.
This strikes me as likely to have an agreed best-practice answer, but I can't seem to find one anywhere.
I have an application that will load and use classes that implement a specific interface. The implementation classes will be written by someone else and I want to send them the minimum they need to successfully implement the interface.
So far the best I've come up with is the following:
The application solution that contains:
A project that contains just the interface definition and compiles to a dll.
A project for the application that uses the interface and references the dll.
A separate solution for an example implementation that builds to a dll and references the interface dll.
Is this the best way to do this? i.e. distribute a compiled version of the interface to anyone that needs to implement the interface.
I tried using just a copy of the interface source files in the example implementation and my application failed to recognise the class as implementing the interface. Is this to be expected or is my class loading code bugged (it does work when the example references the pre-compiled dll)?
you should put your interface in an assembly and then distribute your assembly (or your whole project if needed) so that the other people who want to implement the interface just need to reference your assembly so they have access to the same interface (which is not the case if you just send the interface (.cs) file as your interface will be embedded in another assembly and thus will certainly have another namespace or assembly name and thats why your implementation class was not recognized as inheriting your interface cause basically it was not the same interface even if the methods and properties where the same ;))
i think your approach first is the best if you dont want people to change your code and just use the interface
otherwise just share the whole project containing the interface
That's the approach I've used, and seen in other projects - give the shared assembly a generic name such as MyApp.Interfaces, in case you end up with multiple shared interfaces.
An alternative approach is to use the Managed Extensibility Framework: http://msdn.microsoft.com/en-us/library/dd460648.aspx - but that may be overkill for a small project.