Cloning/serialization produces wrong class because of different dlls - c#

I have a dll library TaskLibrary.dll with a class Execution performing some Operation(s) and a class ParallelizeExecution that takes a single Execution, clones it and executes the Run method of the multiple Execution instances.
The Clone method of the Execution class works by converting the Execution in xml and reverting it back to normal as a new instance
public Execution{
List<AOperation> operations;
public Run(){
foreach(var op in operations){
//...do stuff...
}
}
public Execution Clone(){
MyXmlSerializer.DeserializeObject<Execution>(
MyXmlSerializer.SerializeObject(this));
}
}
public ParallelizeExecution{
List<Execution> toRun;
public RunParallel(Execution e,int numExecutions){
toRun=new List<Execution>();
for(var i=0;i<numExecutions;i++){
toRun.Add(e.Clone());
}
}
}
The Execution class is serializable as is each of the classes implementing Operation. This is obtained by using an abstract class (AOperation) which all the IOperation implementations extend, using the XmlInclude annotation to make MyXmlSerializer work for each IOperation.
[XmlInclude(typeof(Operation1))]
[XmlInclude(typeof(Operation2))]
public abstract class AOperation:IOperation{
...
}
Now I have a new project referencing the TaskLibrary.dll. I need to add a new kind of Operation to a Execution:
public class Operation3: Operation2 {
}
Everything works fine with a single execution, but when I use ParallelizeExecution Operation3 is correctly serialized as Operation2 thus executing an unwanted Run method. How can I add a new type of AOperation to the Execution class and expect it to be correctly serialized and run in the Execution?
OR
How can I avoid the problem without altering the way the Execution class is serialized?
Caveat: I know that it is possible to use Reflection to xmlserialize any tipe extending a given one, but i'd rather learn how to do this using standard OOP (if possible).
EDIT: I could modify TaskLibrary.dll but I'd rather avoid this approach, it would void my efforts in learning new things and aiding the community, moreover it would be quite painful to redistribute the library to those already using it.

You can use the extraTypes argument to the XmlSerializer constructor. Use reflection to find all of the relevant types, and create the XmlSerializer with the complete list. The overall process is laid out here, but for posterity's sake:
// use reflection to get all derived types
List<type> knownTypes = new List<type>();
// Iterate over whichever assembly has your types.
foreach(Type t in Assembly.GetExecutingAssembly().GetTypes())
if (typeof(Car).IsAssignableFrom(t) ||
typeof(Wheel).IsAssignableFrom(t) ||
typeof(Door).IsAssignableFrom(t))
knownTypes.Add(t);
// prepare to serialize a car object
XmlSerializer serializer = new XmlSerializer(typeof(Car), knownTypes.ToArray());

Related

Trying to serialize System.Numerics.Quaternion using protobuf-net

Background Info
I have a .Net Standard 2.0 class library that uses Protobuf-net.grpc's code first approach to define a gRPC service. In this definition I have classes defining different data structures that we are using to record sensor data and serialize this out using protobuf-net. My programs are ingesting serveral hundred thousand large objects /s (which will soon scale into the millions) and are intended to be used in embedded environments.
Problem
In my class below, I would like to include as a member a System.Numerics.Quaterion. I cannot seem to get this serialized out. Using static constructors, the RuntimeTypeModel throws exceptions as the Quaternion model has somehow already been created by the time the static constructor is executed. As this is a class library, and I desperately want to avoid invoking the RuntimeTypeModel in each different program using the gRPC service. I'm hoping to find a way to serialize the System.Numerics.Quaternion.
I have tried placing this static constructor runtime definition at the highest level of the class hierarchy to no avail. Exceptions still thrown.
[ProtoContract]
public class IMUData : SensorData, ISensorData
{
static IMUData()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}
... //Other members
[ProtoMember(8)]
public Quaternion Orientation
{
get; set;
}
... //Other methods and members
}
Question
Is what I would like to do even possible, or should I simply create my own Quaternion class and define implicit operators? (I'd rather avoid this as processing billions of these objects takes long enough)
This is ultimately a timing problem - when the serializer attempts to reflect on SensorData to prepare the serializer, the static constructor in IMUData has not yet executed, so it prepares the serializer with incomplete information, and then later the static constructor tries to reconfigure the model - too late.
If you use C# 9.0, you can fix this by using a module initializer instead of a static constructor (if we assume that SensorData and IMUData are in the same module, which is probably a safe assumption). The following works fine, for example:
[ProtoContract]
public class IMUData : SensorData //, ISensorData
{
[ModuleInitializer]
internal static void Init()
{
RuntimeTypeModel.Default.Add(typeof(Quaternion), false)
.Add("W")
.Add("X")
.Add("Y")
.Add("Z");
}
Note that if you're not using .NET 5 (preview, currently), you can define the necessary attribute yourself:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal sealed class ModuleInitializerAttribute : Attribute { }
}
If this isn't an option, you can simply put the model configuration code much earlier in your application - ideally during startup, so that it happens long before the serializer attempts to start building models.

Allow subclass instantiation only on the assembly of the superclass in C#

Imagine the following scenario in a Xamarin solution:
Assembly A (PCL):
public abstract class MyBaseClass
{
public MyBaseClass()
{
[...]
}
[...]
}
Assembly B (3rd Party Library):
public class SomeLibClass
{
[...]
public void MethodThatCreatesClass(Type classType){
[...]
//I want to allow this to work
var obj = Activator.CreateInstance(classType);
[...]
}
[...]
}
Assembly C (Main project):
public class ClassImplA:MyBaseClass{
[...]
}
public class ClassImplA:MyBaseClass{
[...]
}
public class TheProblem{
public void AnExample(){
[...]
//I want to block these instantiations for this Assembly and any other with subclasses of MyBaseClass
var obj1 = new ClassImplA()
var obj2 = new ClassImplB()
[...]
}
}
How can I prevent the subclasses from being instantiated on their own assembly and allow them only on the super class and the 3rd Party Library (using Activator.CreateInstance)?
Attempt 1
I though I could make the base class with an internal constructor but then, I saw how silly that was because the subclasses wouldn't be able to inherit the constructor and so they wouldn't be able to inherit from the superclass.
Attempt 2
I tried using Assembly.GetCallingAssembly on the base class, but that is not available on PCL projects. The solution I found was to call it through reflection but it also didn't work since the result of that on the base class would be the Assembly C for both cases (and I think that's because who calls the constructor of MyBaseClass is indeed the default constructors of ClassImplA and ClassImplB for both cases).
Any other idea of how to do this? Or am I missing something here?
Update
The idea is to have the the PCL assembly abstract the main project (and some other projects) from offline synchronization.
Given that, my PCL uses its own DB for caching and what I want is to provide only a single instance for each record of the DB (so that when a property changes, all assigned variables will have that value and I can ensure that since no one on the main project will be able to create those classes and they will be provided to the variables by a manager class which will handle the single instantions).
Since I'm using SQLite-net for that and since it requires each instance to have an empty constructor, I need a way to only allow the SQLite and the PCL assemblies to create those subclasses declared on the main project(s) assembly(ies)
Update 2
I have no problem if the solution to this can be bypassed with Reflection because my main focus is to prevent people of doing new ClassImplA on the main project by simple mistake. However if possible I would like to have that so that stuff like JsonConvert.DeserializeObject<ClassImplA> would in fact fail with an exception.
I may be wrong but none of the access modifiers will allow you to express such constraints - they restrict what other entities can see, but once they see it, they can use it.
You may try to use StackTrace class inside the base class's constructor to check who is calling it:
public class Base
{
public Base()
{
Console.WriteLine(
new StackTrace()
.GetFrame(1)
.GetMethod()
.DeclaringType
.Assembly
.FullName);
}
}
public class Derived : Base
{
public Derived() { }
}
With a bit of special cases handling it will probably work with Activator class , but isn't the best solution for obvious reasons (reflection, error-prone string/assembly handling).
Or you may use some dependency that is required to do anything of substance, and that dependency can only be provided by your main assembly:
public interface ICritical
{
// Required to do any real job
IntPtr CriticalHandle { get; }
}
public class Base
{
public Base(ICritical critical)
{
if (!(critical is MyOnlyTrueImplementation))
throw ...
}
}
public class Derived : Base
{
// They can't have a constructor without ICritical and you can check that you are getting you own ICritical implementation.
public Derived(ICritical critical) : base(critical)
{ }
}
Well, other assemblies may provide their implementations of ICritical, but yours is the only one that will do any good.
Don't try to prevent entity creation - make it impossible to use entities created in improper way.
Assuming that you can control all classes that produce and consume such entities, you can make sure that only properly created entities can be used.
It can be a primitive entity tracking mechanism, or even some dynamic proxy wrapping
public class Context : IDisposable
{
private HashSet<Object> _entities;
public TEntity Create<TEntity>()
{
var entity = ThirdPartyLib.Create(typeof(TEntity));
_entities.Add(entity);
return entity;
}
public void Save<TEntity>(TEntity entity)
{
if (!_entities.Contains(entity))
throw new InvalidOperationException();
...;
}
}
It won't help to prevent all errors, but any attempt to persist "illegal" entities will blow up in the face, clearly indicating that one is doing something wrong.
Just document it as a system particularity and leave it as it is.
One can't always create a non-leaky abstraction (actually one basically never can). And in this case it seems that solving this problem is either nontrivial, or bad for performance, or both at the same time.
So instead of brooding on those issues, we can just document that all entities should be created through the special classes. Directly instantiated objects are not guaranteed to work correctly with the rest of the system.
It may look bad, but take, for example, Entity Framework with its gotchas in Lazy-Loading, proxy objects, detached entities and so on. And that is a well-known mature library.
I don't argue that you shouldn't try something better, but that is still an option you can always resort to.

c# - Throwing exceptions from attribute constructor

I found this article on the subject and tried the following:
public class FailerAttr : Attribute {
public FailerAttr(string s) {
throw new Exception("I should definitely fail!");
}
}
And in unit test project I have the following:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class Test {
[TestMethod]
public void GoFail() {
// Make sure attribute will get initialized
new Failer();
}
private class Failer {
[FailerAttr("")]
public int Prop { get; set; }
}
}
When I run the test, it succeeds. So, the questions are:
Why it does not fail?
Is it really a bad idea to throw exceptions from attributes? Because I think I need to.
Some environment info (just in case it's relevant):
Unit tests are run via ReSharper's unit test runner (R# v8.2.0.2160)
Visual studio v11.0.61030.0
Since attributes are part of class definition available to you at runtime (it's also called "metadata" in geekspeak) CLR does not instantiate them unless some part of your program asks for them. This makes sense: why bother spending CPU cycles for something that nobody wants to access?
Because of this, the execution of the constructor will never happen unless you ask for that attribute.
Here is one way to ask for an attribute that would make your program fail:
var attr = Attribute.GetCustomAttribute(typeof(Failer).GetProperty("Prop"), typeof(FailerAttr));
This code makes CLR instantiate the FailerAttr, which triggers the exception.
Demo on ideone.
If you do not know the type of the attribute, you can retrieve all attributes at once with this call:
var allAttributes = Attribute.GetCustomAttributes(typeof(Failer).GetProperty("Prop"));
This causes an exception as well (demo).
Attributes are not converted to executable code, they're converted to metadata.
Metadata like this is not used during normal execution, it is only if you start using the metadata, like through reflection, that the attribute type comes back into play.
The constructor or any of the code in the attribute is not executed during compilation. Instead the type and the parameters to the constructor is serialized into the metadata, and only upon inspection using reflection will the constructor actually be executed.
In other words, if you intend this to fail at compile time then you can't.
Try looking for the attributes using reflection, depending on the attribute object is deserialized from the metadata, the constructor may or may not be invoked, but it will definitely not be invoked by just applying it to identifiers.

Factory pattern using reflection - class registration using static key associated with each class

While studying some patterns I came across the factory pattern to create instances of (unknown) classes. That made me interested hence I want to build a program that can be dynamically enhanced. So I have some basic functionality within one assembly and the actual workers within different assemblies. The only hint that I get from my application is an operation-name. Now I want to create a new worker that relies to the operation. Because I do not know the actual implementations of the workers I've chosen this kind of pattern.
OK, some more details:
I have an IWorker-interface that all my processes implement. A Singleton WorkerFactory lets me create new instances of any worker implemented in any assembly within the same path as the current one. To do so I added a CreateWorker-method to my interface that accept an array of strings (which have been passed as varargs to the console-application).
Before being able to create any instance of any worker I have to register any class to the factory. Unfortunately on C# it is not possible to insert such a behaviour statically into any static context of the worker-classes because the code within this context is only executed when the class is accessed in any way (be it by instantiating it or by accessing any of its static members, see static constructors). So I achieve this by reflecting all the types found within all assemblies with the path of the currently executing assembly.
Now I may check if the current type is implementing the interface and if so the type can be added to the registration-map of the factory containing the operations name (key) and the worker (value) as System.Type (see Factory Pattern using reflection). The problem is: how do I get the actual name of the operation this type refers to.
I think there are two options for this:
I add a static property to every worker-class that stores the operations name. Thus I can refer the operation by reflecting this property on the obtained type.
Adding a non-static property for the name and create a dummy-instance of the actual worker-class while registering.
While the former option has the disadvantage that I cannot ensure that all workers actually have such a static property implemented (hence it is not possible to add a static member to the IWorker-interface) the latter has the disadvantage that every class must have an empty constructor in order to build the dummy-instance from which to get the operations name. Nevertheless this constructor would be publicly accessable whilst not containing any initialization-code.
Having said that all this question is about best or at least better practices on factory pattern using reflection. I think I´d prefer the first option, but maybe I also missed any better solution for this approach.
Hence this thread is already quite long I´d like not to post any code here, but let me know if you need anyway.
You can use custom attributes on your worker classes:
[AttributeUsage(System.AttributeTargets.Class)]
public class WorkerAttribute : Attribute
{
public WorkerAttribute (String operationType)
{
this.OperationType = operationType;
}
public String OperationType {get; private set;}
}
public interface IWorker { }
[WorkerAttribute("Experienced")]
public class ExperiencedWorker: IWorker
{
}
They are accessed like it is described here. It will be something like:
Type attributeType = typeof(WorkerAttribute);
var myWorkerClassesPlusAttributes = from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
let attributes = type.GetCustomAttributes(attributeType, true)
where attributes.Any()
select
new KeyValuePair<String, Type>(((WorkerAttribute)attributes.First()).OperationType,
type);
Dictionary<String, Type> workers = new Dictionary<string, Type>();
foreach (var item in myWorkerClassesPlusAttributes)
workers.Add(item.Key, item.Value);
IWorker worker = (IWorker)Activator.CreateInstance(workers["Experienced"]);
It is not the best and does not cover multiple WorkerAttributes on the class, but can be used as the basis for your solution.

Any design patterns for initialization? C#

I have a class called initialize that runs at the beginning of my program. Originally I explicitly hard coded all the classes that it was supposed to instantiate but I would like to make it more generic and remove the hard coded classes so I can mark the class closed for modification.
My first thought was to create a queue of Types that my initialize class would cycle through and instantiate all the Types that are in the queue.
I then wanted to decide on a per class basis if it should be added to the queue or not. By adding itself to the queue from within the class. The problem is that I cant add a class to the queue unless it is already been instantiated. I know that variables can be initialized before running but obviously not methods. So Im stuck on figuring out weather what I would like to do is possible on not.
Something along the Lines of:
MyClass
{
initalize.instance.Enqueue(typeof(MyClass));
}
I meant something along these lines.
public static class Initializer
{
public static void Initialize()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
foreach (var type in assembly.GetTypes())
if (type.IsDefined(typeof(InitializeAttribute), true))
Console.WriteLine("Need to initialize {0}", type.FullName);
}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class InitializeAttribute : Attribute
{
}
[Initialize]
public sealed class ToBeInitialized
{
}
The pattern that you're looking for, if I understand your question correctly, is the factory method pattern. Take a look at this link: http://en.wikipedia.org/wiki/Factory_method_pattern#C.23
If you're initializing class static state then this isn't necessary. Just add a static constructor to all of your types and the .NET runtime will lazily call the static constructor before any static members of that class are accessed (be it a field, method, property or event). This can also work for the singleton pattern - however as I said, static constructors are JIT-evaluated which can introduce non-deterministic delays in your program.
The alternative is to use reflection to iterate through each Type in the assembly and perform your own initialization. This is how plugin systems work.

Categories