I have been looking at the inner workings of the StockTrader RI for PRISM.
In this RI, MEF and a custom attribute system are used in combination to register views with regions as opposed to hooking up things to the RegionManager in the Module Initializer.
More specifically, there is a ViewExportAttribute which implements:
MetaDataAttribute
IViewRegionRegistration
The MetaDataAttribute and the "Attribute View" IViewRegionRegistration can be leveraged by System.Lazy<T,TMetaData> in AutoPopulateExportedViewsBehavior to achieve proper linking of regions and views.
In general the interplay between System.Lazy<T,TMetaData> and the actual metadata is elaborated here, more specifically the section "Using Strongly-typed Metadata".
To be clear, I understand the intent of Lazy and it clearly works. However, what I completely do not understand is where and how the link occurs between the metadata view supplied by the attribute (which is just an interface) and filling the TMetaData properties with the actual data supplied by the MetaDataAttribute.
To make my request even clearer, from the previously referenced example:
First, an interface is defined that can serve as a sort of template to pass certain metadata:
public interface IMessageSenderCapabilities
{
MessageTransport Transport { get; }
bool IsSecure { get; }
}
Next, A corresponding MetaDataAttribute is defined (which has the same properties as the previous interface)
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class MessageSenderAttribute : ExportAttribute
{
public MessageSenderAttribute() : base(typeof(IMessageSender)) { }
public MessageTransport Transport { get; set; }
public bool IsSecure { get; set; }
}
The attribute can be used in an export, where actual values are set for the attribute properties:
[MessageSender(Transport=MessageTransport.Smtp, IsSecure=true)]
public class SecureEmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
Now finally, we can do some importing:
public class HttpServerHealthMonitor
{
[ImportMany]
public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }
public void SendNotification()
{
foreach(var sender in Senders)
{
if (sender.Metadata.Transport == MessageTransport.Smtp &&
sender.Metadata.IsSecure)
{
var messageSender = sender.Value;
messageSender.Send("Server is fine");
break;
}
}
}
}
In this last step: sender.Metadata.Transport is evaluated on that very Lazy<>. Therefore, somewhere along the way, Lazy is made aware of the actual values of the metadata, not just the interface it gets passed. I want to understand how that happens, who or what is responsible for that. Even if it is just a very general flow.
After some more Reflector I think I can start to formulate an answer, although it turns out a lot of things are happening so this answer might evolve. I am writing it down hear for the benefit of learning this myself.
MEFBootsrapper.Run()
...
MEFBootstrapper.Container.GetExports(...) because CompositionContainer : ExportProvider, ... and ExportProvider defines public Lazy<T, TMetadataView> GetExport<T, TMetadataView>().
Next private Lazy<T, TMetadataView> GetExportCore<T, TMetadataView>(string contractName)
Next internal static Lazy<T, M> CreateStronglyTypedLazyOfTM<T, M>(Export export)
In here, AttributedModelServices.GetMetadataView<M>(export.Metadata) where M is the type of the MetaDataView. Whereas export is itself of type System.ComponentModel.Composition.Primitives.Export and this has a field ExportDefenition of which an inherited AttributedExportDefenition exists.
AttributedExportDefenition.MetaData whose getter contains this._member.TryExportMetadataForMember(out strs);
TryExportMetadataForMember(...) finally has a check type.IsAttributeDefined<MetadataAttributeAttribute> to see if there is a MetadataAttribute applied such as for MessageSenderAttribute in the question.
So this is more or less (very roughly) how we get to the actual metadata on the export and so probably with some more detours these exported metadata will also reach the Lazy although I am still to find out how that would work exactly.
Any feedback would still be appreciated.
Trying to understand what is going on with the code in my original question has spawned another question:
There is a subtle difference between the StockTrader RI and the example provided in the MEF Documentation
In Stocktrader, ViewExportAttribute is defined:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
... omitted for brevity ...
}
The MEF docs give a similar example (also in the original question):
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class MessageSenderAttribute : ExportAttribute
{
public MessageSenderAttribute() : base(typeof(IMessageSender)) { }
public MessageTransport Transport { get; set; }
public bool IsSecure { get; set; }
}
So with the above code blocks, the difference is that in the first case, the attribute derives from the Interface that defines the "metadata view" whereas in the second example, this is not the case; The attribute just has the same properties as the IMessageSenderCapabilities interface.
"No big deal" you would think but then in StockTrader RI:
[ImportMany(AllowRecomposition = true)]
public Lazy<object, IViewRegionRegistration>[] RegisteredViews { get; set; }
Whereas in the MEF Example:
[ImportMany]
public Lazy<IMessageSender, IMessageSenderCapabilities>[] Senders { get; set; }
So here, the difference is that in Stocktrader RI, the type that we are trying to Lazily import is not specified (it is just object) whereas in the second it is defined more specifically (IMessageSender).
The end result is more or less the same, some type is Lazily imported along with metadata.
However, what I would like to also learn is:
If the differences at the individual key points in both examples are related.
Specifically in the stock trader example, how do we know what to import as Lazy? Is it because the ViewExportAttribute specifically derives from IViewRegionRegistration that we can have Lazy<object, ... later on, i.e. that the system knows what to import because only types with that metadata will be imported? All this without specifying that object will actually be views, i.e. UserControls?
Related
Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.
This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".
The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.
A quick example:
public class OrderModel
{
public int Id { get; set; }
public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
public string AdditionalData { get; set; }
}
public class StockFinder
{
public Article Article { get; }
public StockFinder(Article article)
{
Article = article;
}
public virtual double GetInternalStock() { /*...*/ }
public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
public bool UsePremiumAvailability { get; }
public CustomStockFinder(Article article, bool usePremiumAvailability)
: base(article)
{
UsePremiumAvailability = usePremiumAvailability;
}
protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)
public override double GetFreeStock() { /*...*/ }
}
In both cases I wanna do stuff like this
var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally
// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);
// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already
Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.
I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.
I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.
What would be the best design pattern or coding be to implement use cases like this?
I'm a complete beginner here, so this might be a really obvious question, I just can't quite seem to understand or find an answer. I've read the MSDN example and most of it makes complete sense.
In the example, they define the following interfaces and give example usage like this;
public interface IOperation
{
int Operate(int left, int right);
}
public interface IOperationData
{
char Symbol { get; }
}
[Export(typeof(IOperation))]
[ExportMetadata("Symbol", '+')]
public class Add : IOperation
{
public int Operate(int left, int right)
{
return left + right;
}
}
I think I must be misunderstanding something here.
What's the point of IOperationData and ExportMetadata ?
Why can't I just drop them both and add char Symbol {get;} to IOperation ?
Then I could just use Add.Value.Symbol instead of Add.Metadata.Smybol. I guess that's not really a huge change, but it does mean I don't need ExportMetadata. What's the difference between Value and Metadata and why does the example use them like it does? Is Metadata for properties and Value for methods? It doesn't seem very well explained to me.
MEF allows composable parts to provide their metadata. Metadata here is a set of statically-known properties, which is typical for part type, not for the type instance.
Suppose you're building a GUI for calculator in the given example.
Each operation is a plugin here, which being loaded via MEF container. You don't want to instantiate every plugin until user selection, but you want to build the panel with buttons, where each button holds an operation symbol.
That's why you need to use metadata instead of adding char Symbol {get;} to IOperation:
you can access metadata without instantiation of part (this could be expensive);
the metadata belongs to the composable part, and every instance of that part should have the same metadata (although calculator example isn't a good choice for understanding that fact).
You're describing metadata interface IOperationData and applying ExportMetadata attribute to the composable part definition. Then, at run-time, MEF looks at Add class, and dynamically builds IOperationData implementation. The instance of that implementation being initialized with values, provided in ExportMetadata. And, finally, you can access the values of IOperationData implementation with Add.Metadata.Smybol later in host application.
UPDATE.
ExportMetadata allows you to add multiple metadata values, but it is often more convenient to add metadata, using custom attribute, which is inherited from ExportAttribute:
public interface IMyPlugin {}
public interface IMyMetadata
{
int Value1 { get; }
string Value2 { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class MyExportAttribute : ExportAttribute, IMyMetadata
{
public MyExportAttribute(int value1, string value2)
: base(typeof(IMyPlugin))
{
Value1 = value1;
Value2 = value2;
}
public int Value1 { get; private set; }
public string Value2 { get; private set; }
}
Usage:
[MyExport(1, "Orange")]
public class MyPlugin : IMyPlugin {}
I have an application which uses plugins. After creating several of them I've found that a big chunk of code is repeated here and there on them so I want to extract a super "plugin base".
Previous the refactor I had the following structure:
After the refactor I have the next one:
I currently don't find a way to model the fact that the plugin engine has a property settings of type plugin settings and the plugin engine base has a property settings of type plugin settings base. I feel that somehow should be a way to declare that the settings property of the plugin engine base should be a "cast" of the settings property of the plugin engine and to model the fact that they both are the same property.
I'm not sure if the problem is explained enough. Feel free to ask for clarifications.
Thanks.
You can use generics. Create generic base class and specify generic parameter constraint to be of type PluginSettingsBase.
abstract class PluginEngineBase<T>
where T: PluginSettingsBase
{
public abstract T Settings { get; set; }
}
Inherit from base class parametrized by PluginsSettings class (thus it is inherited from PluginSettingsBase)
class PluginEngine : PluginEngineBase<PluginsSettings>
{
public PluginSettings Settings { get; set; }
}
Same with PluginData.
An approach I found:
Base class:
class PluginEngineBase
{
public PluginSettingsBase Settings { get; set; }
}
Inheritor:
class PluginEngine : PluginEngineBase
{
public PluginSettings Settings
{
get
{
return (PluginSettings)base.Settings;
}
set
{
base.Settings = value;
}
}
}
thanks in advance for reading this. I don’t fully understand how/when to use abstracts so I am trying to think about it each project I work on to see if it will all click some day Smile | :)
Also, the mix of accessibility levels (private, protected, internal) with keywords static, abstract, and override tend to leave me a little confused. How do I define this method/property/class....
It's not all a big mystery to me but some projects have me coding in circles when dealing with these topics.
With that said,
I have an application that reads an XML document and outputs text and image files. I’m also storing all of the information in a database. I have it working nicely.
The XML has a standard implementation with required fields and is used by multiple organizations to submit data to my app. All organizations should use (at least) the required nodes/elements that are outlined in the XML implementation guide.
So, I want to have a default data object type to be able to derive a specific organization’s data type for required elements. (If this object is going to be used, these are the fields that must be implemented).
If the org. just uses the default requirements, I can use the default object. If they use additional (optional) fields, I’ll have to create a new type inheriting the default type.
My first thought was to use and abstract class that had protected properties for my bare minimum requirements:
public abstract partial class AbstractDataObject
{
protected string DataObjectName;
protected DateTime? DataObjectDate;
etc...
}
Then, if the organization just uses the required elements of the node and no optional elements, I can use a “default” object.
internal partial class DefaultDataObject : AbstractDataObject
{
public new string DataObjectName { get; set; }
public new DateTime? DataObjectDate { get; set; }
etc...
}
But, if an organization uses optional fields of the required node, I can use a derived organization data object.
internal sealed partial class OranizationDataObject : AbstractDataObject
{
public new string DataObjectName { get; set; }
public new DateTime? DataObjectDate { get; set; }
etc...
//Optional fields used by this organization
public string DataObjectCode { get; set; }
etc...
}
Do I need the abstract class? It seems to me I can just have a DefaultDataObject (something like):
internal partial class DefaultDataObject
{
public virtual string DataObjectName { get; set; }
public virtual DateTime? DataObjectDate { get; set; }
etc...
}
And then:
internal sealed partial class OranizationDataObject : DefaultDataObject
{
public override string DataObjectName { get; set; }
public override DateTime? DataObjectDate { get; set; }
etc...
//Optional fields used by this organization
public string DataObjectCode { get; set; }
etc...
}
I’m just really trying to understand how to define these objects so I can reuse them per organization. Both ways seem to work, but I am hoping to understand how to define them properly.
Getting the XML into above objects:
public DefaultDataObject ExtractXmlData(XContainer root)
{
var myObject = (from t in root.
Elements("ElementA").Elements("ElementB")
select new DefaultDataObject()
{
DataObjectName = (String)t.Element("ChildElement1"),
DataObjectDate =
Program.TryParseDateTime((String)
t.Elements("ChildElement2")
.ElementAtOrDefault(0)
),
etc....
OR
public OranizationDataObject ExtractXmlData(XContainer root)
{
var myObject = (from t in root.
Elements("ElementA").Elements("ElementB")
select new OranizationDataObject()
{
DataObjectName = (String)t.Element("ChildElement1"),
DataObjectDate = Program.TryParseDateTime(
(String)t.Elements("ChildElement2")
.ElementAtOrDefault(0)),
DataObjectCode = (String)t.Element("ChildElement3"),
etc....
Again, thanks for reading. Don't forget to tip your wait staff....
Joe
First of all, your base class doesn't need to be abstract if it's a plain DTO class. If you don't have any functionality that needs to be implemented differently by derived classes, you can simply make it a plain base class which will hold common properties.
Next, there is no point in declaring properties in the base class (abstract in your case), if you are going to hide them (using the new keyword). You first code snippet of DefaultDataObject unnecessarily creates a bunch of new properties with the same name. Remove them completely - they are already defined in the base class.
[Edit] I didn't notice this initially, and #svick warned me, that your base class actually contained fields instead of properties, which makes me wonder why you needed to add the new keyword at all. I went over your code quickly and saw them as properties. In any case, you should never expose public fields - at least change them to auto-implemented properties by adding the { get; set; } block.
In other words, this would simply work:
// this doesn't need to be abstract.
// just put all the common stuff inside.
public class BaseDO
{
// as svick pointed out, these should also be properties.
// you should *never* expose public fields in your classes.
public string Name { get; set; }
public DateTime? Date { get; set; }
}
// don't use the new keyword to hide stuff.
// in most cases, you won't need that's behavior
public class DerivedDO : BaseDO
{
// no need to repeat those properties from above,
// only add **different ones**
public string Code { get; set; }
}
As a side note, but nevertheless important IMHO, you should simplify naming (and make it more clearer what your code does). There is no need to repeat "DataObject" in every property name, for example. But since your code is probably only a simplified version, it doesn't matter.
Lastly, have you heard of XmlSerializer? You don't need to traverse the XML elements manually. It is enough to call XmlSerializer to both serialize and deserialize your data.
Everything I need to know I learned from Sesame Street
Scrub your class design hard to make sure you've identified everything that is the same and different. Play computer, so to speak, with your classes and see how they do the same, different, or the same thing but in different ways.
What is the same, different, same but differently will likely change as you play computer.
Think in general terms of the two pillars of OO Classes. Polymorphism and Inheritance
As you do the above that is. Not so much in terms of C# implementation per se.
How things clump into same vs. different will help drive implementation
And it's all relative.
More of same default behavior? Perhaps a concrete base class instead of abstract.
More of same thing, but differently? Perhaps an abstract class instead of concrete base class.
A default way of doing x? Perhaps a virtual method.
Everyone does the same thing, but no two the same way? A delegate perhaps.
Implementation Suggestions
Make methods and fields protected as a default. Private does not get inherited. Designs change, stay flexible. If something just has to be private, fine.
virtual means you can change implementation in a sub class. It does not mean you must.
Folks seem to under-utilize delegates. They're super for polymorphic methods.
There is nothing wrong with public fields. What's the practical difference between a public field and a public auto-implemented property? Nothing. They both directly return (or set) the underlying value. So what's the point of even bothering with properties? If you want to publicly expose an underlying value differently than it's "natural" state. For example, returning a number in a specific format. And of course you can have different properties for the same field.
A Property can have a get without a set. Or vice versa. Also get and set can have different access levels. Often you'll see this as a public get and a protected (or private) set.
It depends on what the derived types will want to do. If they are going to use the default implementation and only expand on it somehow, then having the default class as the non-abstract base class is fine.
On the other hand, if they are most likely going to re-implement the functionality, you should have an abstract base class (or an interface) and a separate default class.
If you for some reason don't know which one is it, you can let the inheritors choose by having an abstract base class and leaving the default class unsealed.
Also, looking at your code, it seems you misunderstand what the various keywords do. Most of the time, you do not want to use new like this. What it does is to define another member with the same name, unrelated to the original one. Also, there's no reason to override something if you don't want to change it. So, if you expect that the derived classes won't have to reimplement the properties, you don't have to make them virtual at all.
An abstract class can already implement things that can be inherited
public abstract class DataObjectBase
{
public string DataObjectName { get; set; }
public DateTime? DataObjectDate { get; set; }
}
A concrete class can add new properties and methods
public class DerivedDataObject : DataObjectBase
{
public int NewProperty { get; set; }
}
The properties DataObjectName and DataObjectDate are already available in the new class, because they are automatically inherited from the base class.
If the abstract class defined an abstract member, however, you would have to implement it in the derived class.
Say the base class defines
public abstract void SomeMethod(string name);
The the derived class has to do this
public override void SomeMethod(string name)
{
...
}
If your base class does not have abstract members, it does not need to be abstract and can play the role of your default data object directly.
The keyword 'partial` is not needed here. It is only useful if you want to split one class into several pieces over several files.
The keyword new is wrong here. It is used to shadow an inherited member. This means that the inherited member will be hidden "behind" the new declaration. What you need, is to override. This does not hide a member, but provide an alternative implementation of the same member in the derived class.
Is it somehow possible to extend a type, wich is defined in another assembly, to add an attribute on one of its properties?
Exemple I have in assembly FooBar:
public class Foo
{
public string Bar { get; set; }
}
But in my UI assembly, I want to pass this type to a third party tool, and for this third party tool to work correctly I need the Bar property to have a specific attribute. This attribute is defined in the third party assembly, and I don't want a reference to this assembly in my FooBar assembly, since FooBar contains my domain an this is a UI tool.
You can't, if the thirdy-party tool uses standard reflection to get the attributes for your type.
You can, if the third-party tool uses the TypeDescriptor API to get the attributes for your type.
Sample code for the type descriptor case:
public class Foo
{
public string Bar { get; set; }
}
class FooMetadata
{
[Display(Name = "Bar")]
public string Bar { get; set; }
}
static void Main(string[] args)
{
PropertyDescriptorCollection properties;
AssociatedMetadataTypeTypeDescriptionProvider typeDescriptionProvider;
properties = TypeDescriptor.GetProperties(typeof(Foo));
Console.WriteLine(properties[0].Attributes.Count); // Prints X
typeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(
typeof(Foo),
typeof(FooMetadata));
TypeDescriptor.AddProviderTransparent(typeDescriptionProvider, typeof(Foo));
properties = TypeDescriptor.GetProperties(typeof(Foo));
Console.WriteLine(properties[0].Attributes.Count); // Prints X+1
}
If you run this code you'll see that last console write prints plus one attribute because the Display attribute is now also being considered.
No. It's not possible to add attributes to types from separate assemblies.
What you can do, though, is create your own type that wraps the third-party type. Since you have full control over your wrapper class, you can add the attributes there.
What about:
public class Foo
{
public virtual string Bar
}
public class MyFoo : Foo
{
[yourcustomattribute]
public overrides string Bar
}
What I think you need is some kind of adapter layer that will not let that infrastructure dependency leak into your domain logic. Maybe you can create an adapter class that will be like a data transfer object to the other technology. This class lives in an integration assembly that has a dependency on the 3rd party library:
public class FooDTO {
[TheirAttribute]
public string Bar { get; set; }
}
You can then use something like AutoMapper to ease the pain of changing representations.
The ideal solution, though, is if the 3rd party library supported additional ways to provide metadata about their operations. Maybe you can ask them for this feature.