Is there any way to save an entire class definition for a C# object to a file / data store?
I use the [Serializable] tag and ISerializable interface to do this already, but both of these rely on the object definition being in the assembly at run time.
What I'm looking for is a solution to the following scenario:
1) User creates object MyClass in my software and saves it
For the purpose of this example, MyClass is a stand-alone object that doesn't rely on any other class in the system:
i.e. this could be the entire definition:
public class MyClass
{
public int MyProperty { get; set; }
public void DoSomething() { /* do something, like Console.Write(""); */ }
}
2) We release a patch that removes MyClass from the system
3) User loads the saved MyClass from step 1 and calls DoSomething() on it - and has the function work exactly the same as it did before the patch removed the class from the system
Is there any way this can be done without reflection / emit trickery?
No, this won't work without emitting the type definition. What you are trying to do is actually save off the code (otherwise, how would DoSomething work?) - which is what the compiler does for you. Plain serialization will never work for you here.
So, if you need to save behavior as well as state, you need to either keep the historical code around, use some type of reflection emit trickery to persist the type definition as a loadable assembly, or use dynamic programming tricks that treat data as executable code.
When I have had do versioned serialization before, I normally have custom serialization logic and a "version" attribute on the object - using this I can create a type that I've moved and renamed - say SomeClass to Archive.SomeClassV3. You can use Version Tolerant Serialization for this, but I prefer to implement ISerializable and use serialization proxies if this is required. (Well, actually I prefer to avoid this problem altogether!)
Well, you could keep all of these serializable classes in their own DLLs, package the DLLs with the application, and have the DLLs loaded at runtime. That way, even if you remove the classes from the latest version of the application, the loaded DLLs will still work.
This seems like a scary approach, though ... now you have clients running ancient code that you no longer even have in your source control repository. How are you supposed to debug that?
You talking about not class-property serialization, but about process-serialization (or method-, doesn't matter). But unlike property serialization, this should contain MSIL-code that runs when you need it. So you must somehow translate it to a bin-code and then run by Assembly.Load, for example. I guess this is not an easy way to do this. So, if this is possible - store your implementation of MyClass to a separate dll, or as a string (in c# language) for further compilation and execution by reflection.
Related
I need to use a iOS build setting in Unity3d that strips unused classes from bytecode but as it uses static analysis to discover which to remove- so any classes resolved through reflection will not be excluded from removal unless explicitly added to an exclusion list. I managed to remove all uses of reflection in my own code, but Mono itself seems to use a reflection based configuration to do a bunch of stuff and I've already added about a dozen classes to the exclusion list but now I'm to the point where exceptions are not giving any clues as to what class needs to be excluded for them to work.
My question is, is it possible to get a precise list of all the classes (with source assembly and namespace) resolved through reflection throughout every assembly that the application uses, and how would you go about it? I have Visual Studio 2012 and while I know it has powerful debugging tools I don't know how I would use them to this end.
Thanks.
The short version
You can't as there is no way to find all lookups via reflection using static analysis.
The long version
Just think of the following example: I write code that selects a class depending on user input, e.g. in pseudo code:
string action = ... ; // get some user input here, e.g. "Fire"
string clazz = "Do" + action;
var obj = Activator.CreateInstance("MyActions", clazz);
As you can see the actual full class name is not occuring anywhere in the code. So you would need to execute the code in every possible way to find out which values the clazz variable could assume. Therefore you cannot find out which classes this code would access via reflection.
Further Questions
What exact API from Mono are you using and what kind of exceptions are you getting? Maybe there is some alternative that could be used for your purpose.
We have code that is called by an external framework, ARDEN. Short of a comment (easily overlooked), how can I effectively notify developers of tie in's to this framework? Specifically, a tie in couples the CLASS, NAMESPACE and METHOD to said framework.
namespace MyCompany//changing namespace for this class is NOT SAFE
{
public class MyClass//changing class name is NOT SAFE
{
[TiedToArdenAttribute]//maybe an attribute?
public void MethodCalledByArden() {}//adding params, changing name is NOT SAFE
public void NotCalledByArden() {}//changing this method signature, name, params is OK
}
}
Under normal circumstances, for example when I change the name of MyClass in an assembly via visual studio I can't compile without fixing the references to said class. If the namespace, classname or method name changes...there should be a warning that says "best fix Arden to deal with this change". I considered an Error, but since there's no way to verify Arden is fixed I don't believe that will work.
Is there a way to achieve a similar result for this external framework?
I think whatever you do can be undone by other developers - they can rename class, remove comments, remove attributes.
Try to move this class to separate library instead. And in your project add reference to compiled assembly. That will make class name fixed in your project.
If others are using the code, it is best to talk in terms of contracts and not class instances via interfaces. By allowing the consumer to use an Interface will dictate the primary changes such as property changes...but things like internal class name changes will not affect a consumer. Plus you can version your classes, while working on a new class, the old class could still be used by the consumer until the factory internally releases it, without the consumer knowing that V2 of the class is being used.
[ Updated 25 May 2010 ]
I've recently upgraded from VS2008 to VS2010, and at the same time upgraded to .Net 4.
I've recompiled an existing solution of mine and I'm encountering a Cast exception I did not have before.
The structure of the code is simple (although the actual implementation somewhat more complicated).
Basically I have:
public class SomeClass : ISomeClass
{
// Stuff
}
public static class ClassFactory
{
public static IInterface GetClassInstance<IInterface>(Type classType)
{
return (IInterface)Activator.CreateInstance(classType); // This throws a cast exception
}
}
// Call the factory with:
ISomeClass anInstance = ClassFactory.GetClassInstance<ISomeClass>(typeof(SomeClass));
Ignore the 'sensibleness' of the above - its provides just a representation of the issue rather than the specifics of what I'm doing (e.g. constructor parameters have been removed).
The marked line throws the exception:
Unable to cast object of type
'Namespace.SomeClass' to type
'Namespace.ISomeClass'.
I suspect it may have something to do with the additional DotNet security (and in particular, explicit loading of assemblies, as this is something my app does).
The reason I suspect this is that I have had to add to the config file the setting:
<runtime>
<loadFromRemoteSources enabled="true" />
</runtime>
.. but I'm unsure if this is related.
Update
I see (from comments) that my basic code does not reproduce the issue by itself. Not surprising I suppose. It's going to be tricky to identify which part of a largish 3-tier CQS system is relevant to this problem.
One issue might be that there are multiple assemblies involved. My static class is actually a factory provider, and the 'SomeClass' is a class factory (relevant in that the factories are 'registered' within the app via explicit assembly/type loading - see below) .
Upfront I use reflection to 'register' all factories (i.e. classes that implement a particular interface) and that I do this when the app starts by identifying the relevant assemblies, loading them and adding them to a cache using (in essence):
Loop over (file in files)
{
Assembly assembly = Assembly.LoadFile(file);
baseAssemblyList.Add(assembly);
}
Then I cache the available types in these assemblies with:
foreach (Assembly assembly in _loadedAssemblyList)
{
Type[] assemblyTypes = assembly.GetTypes();
_loadedTypesCache.AddRange(assemblyTypes);
}
And then I use this cache to do a variety of reflection operations, including 'registering' of factories, which involves looping through all loaded (cached) types and finding those that implement the (base) Factory interface.
I've experienced what may be a similar problem in the past (.Net 3.5, so not exactly the same) with an architecture that involved dynamically creating classes on the server and streaming the compiled binary of those classes to the client app. The problem came when trying to deserialize an instance of the dynamic class on the client from a remote call: the exception said the class type was not know, even though the source and destination types were exactly the same name (including namespace). Basically the cross boundry versions of the class were not recognised as being the same. I solved that by intercepting the deserialization process and explicitly defining the deseriazation class type in the context of the local assemblies.
This experience is what makes me think the types are considered mismatched because (somehow) the interface of the actual SomeClass object, and the interface of passed into the Generic method are not considered the same type.
So (possibly) my question for those more knowledgable about C#/DotNet is: How does the class loading work that somehow my app thinks there are two versions/types of the interface type and how can I fix that (keeping in mind its a DotNet 3.5 vs 4 issue as it worked before my upgrade) ?
[ whew ... anyone who got here is quite patient .. thanks ]
I would say yes that it has something to do either with the runtime loading of assemblies, or with the upgrade conversion, I used this code in a new project and had no issues. Can you provide more code to replicate the error?
The 'quick' (ITO implementation, not ITO finding it) solution was to stop the shadow copy of my app's DLLs.
This is done by modifying the ASP.Net app's Web.Config file as follows:
In section 'configuration/web.settings', add setting:
<hostingEnvironment shadowCopyBinAssemblies="false" />
When I attempt to use dotfuscate on my application, I get an application error when I run it.
Dotfuscator (and all obfuscators) are typically safe to run on an application, but they do occasionally cause problems. Without specific details of your problem, it's difficult to diagnose.
However, one common problem with obfuscators is when you mix them with reflection. Since you're changing the type names, but not strings, any time you try to reflect on objects with a specific string name, and use the reflection namespace to construct objects, you'll likely have problems.
Most of the problem I have encountered with obfuscation revolve around types that can't have their name changed, because something needs to reflect on them (your code or the runtime).
for example if you have a class that is being used as a web service proxy, you can't safely obfuscate the class name:
public class MyWebServiceProxy : SoapHttpClientProtocol
{
}
Also some obfuscators can not handle generic methods and classes.
The trick is you need to find these types and prevent the obfuscater from renaming them. This is done with the Obfuscation attribute:
[global::System.Reflection.Obfuscation(Exclude=true, Feature="renaming")]
Another thing that can be a problem with obfuscators is serialization using BinaryFormatter, since it changes the field names. I have some users who use protobuf-net for serialization on their obfuscated code for this reason.
I have wondered about the appropriateness of reflection in C# code. For example I have written a function which iterates through the properties of a given source object and creates a new instance of a specified type, then copies the values of properties with the same name from one to the other. I created this to copy data from one auto-generated LINQ object to another in order to get around the lack of inheritance from multiple tables in LINQ.
However, I can't help but think code like this is really 'cheating', i.e. rather than using using the provided language constructs to achieve a given end it allows you to circumvent them.
To what degree is this sort of code acceptable? What are the risks? What are legitimate uses of this approach?
Sometimes using reflection can be a bit of a hack, but a lot of the time it's simply the most fantastic code tool.
Look at the .Net property grid - anyone who's used Visual Studio will be familiar with it. You can point it at any object and it it will produce a simple property editor. That uses reflection, in fact most of VS's toolbox does.
Look at unit tests - they're loaded by reflection (at least in NUnit and MSTest).
Reflection allows dynamic-style behaviour from static languages.
The one thing it really needs is duck typing - the C# compiler already supports this: you can foreach anything that looks like IEnumerable, whether it implements the interface or not. You can use the C#3 collection syntax on any class that has a method called Add.
Use reflection wherever you need dynamic-style behaviour - for instance you have a collection of objects and you want to check the same property on each.
The risks are similar for dynamic types - compile time exceptions become run time ones. You code is not as 'safe' and you have to react accordingly.
The .Net reflection code is very quick, but not as fast as the explicit call would have been.
I agree, it gives me the it works but it feels like a hack feeling. I try to avoid reflection whenever possible. I have been burned many times after refactoring code which had reflection in it. Code compiles fine, tests even run, but under special circumstances (which the tests didn't cover) the program blows up run-time because of my refactoring in one of the objects the reflection code poked into.
Example 1: Reflection in OR mapper, you change the name or the type of the property in your object model: Blows up run-time.
Example 2: You are in a SOA shop. Web Services are complete decoupled (or so you think). They have their own set of generated proxy classes, but in the mapping you decide to save some time and you do this:
ExternalColor c = (ExternalColor)Enum.Parse(typeof(ExternalColor),
internalColor.ToString());
Under the covers this is also reflection but done by the .net framework itself. Now what happens if you decide to rename InternalColor.Grey to InternalColor.Gray? Everything looks ok, it builds fine, and even runs fine.. until the day some stupid user decides to use the color Gray... at which point the mapper will blow up.
Reflection is a wonderful tool that I could not live without. It can make programming much easier and faster.
For instance, I use reflection in my ORM layer to be able to assign properties with column values from tables. If it wasn't for reflection I have had to create a copy class for each table/class mapping.
As for the external color exception above. The problem is not Enum.Parse, but that the coder didnt not catch the proper exception. Since a string is parsed, the coder should always assume that the string can contain an incorrect value.
The same problem applies to all advanced programming in .Net. "With great power, comes great responsibility". Using reflection gives you much power. But make sure that you know how to use it properly. There are dozens of examples on the web.
It may be just me, but the way I'd get into this is by creating a code generator - using reflection at runtime is a bit costly and untyped. Creating classes that would get generated according to your latest code and copy everything in a strongly typed manner would mean that you will catch these errors at build-time.
For instance, a generated class may look like this:
static class AtoBCopier
{
public static B Copy(A item)
{
return new B() { Prop1 = item.Prop1, Prop2 = item.Prop2 };
}
}
If either class doesn't have the properties or their types change, the code doesn't compile. Plus, there's a huge improvement in times.
I recently used reflection in C# for finding implementations of a specific interface. I had written a simple batch-style interpreter that looked up "actions" for each step of the computation based on the class name. Reflecting the current namespace then pops up the right implementation of my IStep inteface that can be Execute()ed. This way, adding new "actions" is as easy as creating a new derived class - no need to add it to a registry, or even worse: forgetting to add it to a registry...
Reflection makes it very easy to implement plugin architectures where plugin DLLs are automatically loaded at runtime (not explicitly linked at compile time).
These can be scanned for classes that implement/extend relevant interfaces/classes. Reflection can then be used to instantiate instances of these on demand.