When composing or using ExportProvider.GetExportedValues Method. Exception CompositionContractMismatchException is thrown. I'm converting legacy code that was sprinked with static factories, so I simply want to expose there return values to MEF container, for example.
namespace fooProject
{
static class SomeExportFactory
{
[Export(typeof(IFoo))]
public static FooImp Generate()
{
return new FooImp();
}
}
}
So, this simple illustration would throw an exception with this message "Cannot cast the underlying exported value of type 'fooProject.SomeExportFactory.Generate (ContractName="IFoo")' to type 'IFoo'." to type "IFoo".].
Any guesses to what could be causing this? I already scoured the internet and CompositionContractMismatchException when trying to use MEF with MVC controller is the closes thing I can find, but I do not have duplicate assemblies like in that case.
Ok, I found the answer. Don't export from static functions!!!. Hope this helps someone else in this situation.
MEF throws a cryptic exception if you are trying to exporting from a static function. The exception looks like a potentially duplicate assemblies loaded. Like some answers have suggested, but alas.
For people that are interested in more details read on (links to current MEF implementations are provided).
The code brakes down at ContractServices.cs. You will find a public static function "TryCast" there. It provides a mechanism for MEF to provide instance of the object boxed to a specified type. But it only checks for 2 conditions. First, the object passed in, is already of desired type. Second, object is provided through ExportedDelegate (probably how member function Export works). If your export does not fit any of these then false is returned and immediately CompositionContractMismatchException is thrown (see ExportServices.cs T CastExportedValue(ICompositionElement element, object exportedValue) function).
I wish they would have throw DummyDontUseStaticException in this situation :p
Related
I have a C# class that has a property(name is List) of type Microsoft.VisualBasic.Collection. We need to exposed this property to COM. For that, I was writing an interface for my class such that the property would marshaled as of UnmanagedType.IDispatch.
Something like this:
[DispId(0x68030000)]
Collection List { [DispId(0x68030000)] [return: MarshalAs(UnmanagedType.IDispatch)] get; }
This piece of code was earlier in VB and was being used by C++ as tye VT_DISPATCH. However, while building the C# library, I get the following error:
C:\Program Files
(x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(4335,5):
error MSB3212: The assembly "Name.dll" could not be converted to a
type library. Type library exporter encountered an error while
processing 'Namespace.InterfaceName.get_List(#0), ProjectName'. Error:
Error loading type library/DLL.
I read through few of the posts online which suggested that such errors might cause because of repetitive GUIDs. But that is not the case. I tried with multiple GUIDs. I don't feel this is an issue with any other attribute that I had set on my Interface since, I am able to marshal other properties and function calls ( some of them use primitive types and others use custom classes) successfully.
This is how it is consumed in the consuming C++ application:
LPDISPATCH result;
InvokeHelper(0x68030000, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL);
return result;
This has become a go live issue with the client and I really do not have much time to continue investigation since this is due tomorrow.
Appreciate any help!
I don't think Microsoft.VisualBasic.Collection is COM-visible. Therefore, you cannot use this type as a return value or parameter in a COM class or interface. However, ICollection (which Microsoft.VisualBasic.Collection implements) is COM visible. If that would suit your purposes, use that as the type of your property rather than Microsoft.VisualBasic.Collection.
I have a huge code base and I recently made a change where I changed the type of a parameter from String to a custom class. On the next compile I got all the areas where the impact was, but areas where the input type was of type Object failed. for e.g.
String str = "32"
int i = Convert.ToInt32(str)
Now I have changed String to a new custom type lets say MyCustomClass I would now want following code to fail on next compile
MyCustomClass str = new MyCustomClass("32")
int i = Convert.ToInt32(str)
but it won't as Convert.ToInt32 also accepts type Object. Is there some way I can make a change in MyCustomClass that it's not considered Object anymore.
Please note: Convert.ToInt32 is only used for sample I have many more such functions, so please focus your suggestion/answer to question asked.
Override ToString() and IConvertible
You said in the comments that your intentions are to find places where your object, which had previously been treated as a string, and are now being treated as an object.
In these situations typically, the third-party code would call .ToString() on your object to get something which it can use.
So, Convert.ToInt32(str) is equivalent to Convert.ToInt32(str.ToString()).
If you implement ToString() and IConvertible to return whatever your old version of str looked like then it should continue to work in the same way as the old version.
Probably.
Sorry I know that is not the 100% perfect compile time answer you were looking for, but I think you also know very well that your MyCustomClass will always be considered object.
Possible compile time answer:
Write a tool which uses reflection to iterate over every class/struct/interface in every system/third-party DLL.
Output a load of CS files which contain all these same classes, but just throw NotImplementedException.
(T4 could help you do this)
Compile these classes into dummy.dll
Your .csproj now references only this one dummy.dll, instead of the real dlls.
Your project should compile fine against the dummy dll.
Look at your dummy.cs files and delete any use of object.
Re-compile... and suddenly you get a load of compile time errors showing you anywhere you are using an object.
Impliment an implicit cast from MyCustomClass to String.
public static implicit operator string(MyCustomClass str)
{
return "Legacy respresentation of str";
}
This allows the complier the choice of choosing ToInt32(Object) or ToInt32(String), and I bet it favours the later.
This way all your existing function calls will remain the same so you wont have to be concerned about third party implentation details.
(Sorry, I am not at a computer right now so I can`t test that my assumtion is correct. If you do test this, be sure to consider extension methods, as they can affect the conpilers desision making in unexpected ways)
I am implementing an IDictionary interface, which has parameter object for its get set.
object this [object key] { get; set; }
I want to enforce the key to be type of string, so in my code I do:
(if key.GetType() != typeof(string)) {
//
}
I want to throw an exception when this happen. However I don't know what the most appropriate exception to use in this case. The closest one I can find is TypeInitializationException and ArgumentException. However, it is stated in this document: "Do throw System.ArgumentException or one of its subtypes if bad arguments are passed to a member", which makes me wonder if mine is the right use case for it.
What should I use my case? Should I use Assert instead of throwing Exception?
ArgumentException is the correct exception. The entire BCL uses it and so should you. TypeInitializationException does not fit at all. It has one use case only: a throwing static ctor.
That said, if you are not producing a library (just internal code) you can deviate from that convention if there is a good reason. If you want to use a Debug.Assert or some alternative, feel free to do it.
First I think, the best solution is Mathhew's; Why you just not using the Generic dictionary of type string.
If you need to apply the other approach than Code Contracts is the best way to do that.
Example:
Contract.Requires(key is string);
etc.
Assert is not suitable for this problem but ArgumentException can be applied.
Thanks
I got curious as to where Type.GetType() is implemented, so I took a peek at the assembly and noticed Type.GetType() calls base.GetType() and since Type inherits from MemberInfo I took a look and it is defined as _MemberInfo.GetType() which returns this.GetType(). Since I cannot find the actual code that shows how C# can get type information I would like to know:
How does the CLR get Type and MemberInfo from objects at Runtime?
The ACTUAL source for .NET Framework 2.0 is available on the internet (for educational purposes) here: http://www.microsoft.com/en-us/download/details.aspx?id=4917
This is the C# Language implementation. You can use 7zip to unpack it. You will find the reflection namespace here (relatively):
.\sscli20\clr\src\bcl\system\reflection
I am digging for the specific implementation you are asking about, but this is a good start.
UPDATE: Sorry, but I think its a dead end. Type.GetType() calls to the base implementation which comes from System.Object. If you inspect that codefile (.\sscli20\clr\src\bcl\system\object.cs) you will find the method is extern (see code below). Further inspect could uncover the implementation, but its not in the BCL. I suspect it will be in C++ code somewhere.
// Returns a Type object which represent this object instance.
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern Type GetType();
UPDATE (AGAIN): I dug deeper and found the answer in the implementation of the CLR virtual machine itself. (Its in C++).
The first piece of puzzle is here:
\sscli20\clr\src\vm\ecall.cpp
Here we see the code that maps the external call to an C++ function.
FCFuncStart(gObjectFuncs)
FCIntrinsic("GetType", ObjectNative::GetClass, CORINFO_INTRINSIC_Object_GetType)
FCFuncElement("InternalGetHashCode", ObjectNative::GetHashCode)
FCFuncElement("InternalEquals", ObjectNative::Equals)
FCFuncElement("MemberwiseClone", ObjectNative::Clone)
FCFuncEnd()
Now, we need to go find ObjectNative::GetClass ... which is here:
\sscli20\clr\src\vm\comobject.cpp
and here is the implementation of GetType:
FCIMPL1(Object*, ObjectNative::GetClass, Object* pThis)
{
CONTRACTL
{
THROWS;
SO_TOLERANT;
DISABLED(GC_TRIGGERS); // FCallCheck calls ForbidenGC now
INJECT_FAULT(FCThrow(kOutOfMemoryException););
SO_TOLERANT;
MODE_COOPERATIVE;
}
CONTRACTL_END;
OBJECTREF objRef = ObjectToOBJECTREF(pThis);
OBJECTREF refType = NULL;
TypeHandle typeHandle = TypeHandle();
if (objRef == NULL)
FCThrow(kNullReferenceException);
typeHandle = objRef->GetTypeHandle();
if (typeHandle.IsUnsharedMT())
refType = typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();
else
refType = typeHandle.GetManagedClassObjectIfExists();
if (refType != NULL)
return OBJECTREFToObject(refType);
HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_RETURNOBJ, objRef, refType);
if (!objRef->IsThunking())
refType = typeHandle.GetManagedClassObject();
else
refType = CRemotingServices::GetClass(objRef);
HELPER_METHOD_FRAME_END();
return OBJECTREFToObject(refType);
}
FCIMPLEND
One last thing, the implementation of GetTypeHandle along with some other supporting functions can be found in here:
\sscli20\clr\src\vm\object.cpp
The most significant parts of reflection are implemented as part of the CLI itself. As such, you could look at either the MS CLI reference source (aka "Rotor"), or the mono source. But: it will mostly be C/C++. The public API implementation details (MethodInfo, Type etc) may be C#.
It might not answer you question directly. However, here is a little outline of how managed code knows everything about types.
Whenever you compile code the compiler analyzes/parses the source files and collects information it encounters. For example take a look at class below.
class A
{
public int Prop1 {get; private set;}
protected bool Met2(float input) {return true;}
}
The compiler can see that this is an internal class with two members. Member one is a property of type int with private setter. Member 2 is a protected method with name Met2 and type boolean that takes float input (input name is 'input'). So, it has all this information.
It stores this information in the assembly. There are a couple of tables. For example classes (types) all leave in one table, methods live in another table. Think in turms of SQL tables, though they are definitely are not.
When a user (developer) wants to know information about a type it calls GetType method. This method relies on objects hidden field - type object pointer. This object is basically a pointer to a class table. Each class table will have a pointer to the first method in methods table. Each method record will have a pointer to the first parameter in the parameters table.
PS: this mechamism is key to making .NET assemblies more secure. You cannot replace pointers to methods. It will break the signature of the assebmly.
JIT compilation relies heavily on this tables as well
As #GlennFerrieLive points out, the call to GetType is an InternalCall which means the implementation is within the CLR itself and not in any of the BCL.
My understanding is that the internal CLR method takes the runtime type information from the this pointer, which basically amounts to the name of the type. It then look up the complete type information from the metadata present in all loaded assemblies (presumably, in the current appdomain), which is what makes reflection rather expensive. The metadata area is basically a database of all the types and members present in the assembly and it constructs an instance of Type or Method|Property|FieldInfo from this data.
We have a helper assembly that assists developers with logging information. The specific method used for logging has two signatures:
LogToULS(string message)
LogToULS(string message, Microsoft.Sharepoint.Administration.SPDiagnosticsCategory category)
In my application I have created a static class that contains an instance of the SPDiagnosticsCategory that I would like to be used any time the application logs something. If the first signature is used, a generic category is assigned and it is harder to find logged information specific to this application.
My question is if it's possible to force people to use the second signature any time LogToULS is called from this application or does this need to be accomplished through programmer education?
If you can't remove the method from the codebase, you could mark it as deprecated, so other programmers get a compiler warning whenever they call it (and IntelliSense will warn against its usage):
[Obsolete("Use LogToULS(string, SPDiagnosticsCategory) instead."]
public void LogToULS(string message)
{
// ...
}
As per the ObsoleteAttribute documentation, you can pass true as a second parameter to its constructor to cause a compiler error (not just a warning), but this may break existing code.
Define the first overload as:
public void LogToULS(string message)
{
LogToULS(message, genericErrorCodeHere);
}
Then, make Resharper inline this method so all existing call sites get updated. Next, delete the old, obsolete overload.