I'm looking for anyone that can identify if this is possible or not, I am currently writing a small but extensible application that will have a plugin architecture.
To ensure the application is applicably to the current application, I'm using a custom Attribute to attach to the assembly
[AttributeUsage(AttributeTargets.Assembly)]
class PluginAttributes: Attribute
{
public PluginAttributes(string name, string description, string version, string author)
{
Name = name;
Description = description;
Version = version;
Author = author;
}
public string Name { get; private set; }
public string Description { get; private set; }
public string Version { get; private set; }
public string Author { get; private set; }
public XXXXXX Implements { get; private set; }
}
What I aiming for, is that the 'Implements' property will identify the appropriate plugin's Interface type. I have numerous interfaces defined in the library, such as ICompress, IEncrypt, ILogging, etc.
The attribute will be used to classify which type of plugin it is, without having to create a separate attribute for each.
I know I could have it passed as a string and use reflection, or use an enum, but I want the code to be as low-maintenance as possible, so that plugins can be developed without touching the core of the application.
I have made various of this type of plugin mechanism, and often it is easier to create an instance of the plugin class and check against various interfaces than to define it on a attribute or so. This will leave the door open for a plugin to implement more than one interface, which is nice.
You can do that like this using reflection (assuming you know the type name):
object plugin = Activator.CreateInstance("Assembly.Name", "Type.Class.Name");
if (plugin is ILogging)
{ ... }
if (plugin is IEncrypt)
{ ... }
For your current code, I suggest you to make the type of your Implements property Type and fill it using typeof(ILogging), typeof(IEncrypt), etc.
Related
I have a .NET Core C# app that is referencing several third-party libraries. Each of these libraries has an object that I need to use in my app. There's one catch, my database has two properties associated with each of the properties in each of the classes I need in the third-party libraries. Those two properties are Name and Description.
In an ideal world, each of these third-party libraries would use my base class that has Name and Description :). Since that's not going to happen, I was wondering if there was a way in .NET Core to dynamically create a new type, and add properties from another type using Reflection.
I've seen examples of creating a new type via Roslyn using a string of Text. However, I don't want to use a string of text. I'd rather define a type using pure code. Then, I'd like to use Reflection to 1) get this list of the properties on the third-party class and 2) add them to my new type.
I know how to get a list of properties from a Type using Reflection. However, I'm not sure how to use Rosalyn to 1) Create a new type and 2) add new properties to that type. Is that even possible in the .NET Core world? I know it was in .NET pre-.NET Core days. But, I can't seem to figure out how to do it in .NET Core.
Let's say you have this third party class:
class SomeThirdPartyClass
{
public object Foo { get; set; }
public object Bar { get; set; }
}
If you need to add properties, just subclass it and add them:
class MyClass : SomeThirdPartyClass
{
public string Name { get; set; }
public string Description { get; set; }
}
//Example use
var o = new MyClass();
o.Name = "Name"; //Custom property
o.Foo = new object(); //Base property
If the third party class is sealed, you can wrap it instead.
class MyClass<T>
{
public string Name { get; set; }
public string Description { get; set; }
public T Item { get; set; }
}
//Example use
var o = new MyClass<SomeThirdPartyClass>
{
Item = new SomeThirdPartyClass()
};
o.Name = "name"; //Custom property
o.Item.Foo = new object(); //Base property
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;
}
}
}
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.
A simple example.
alt text http://img19.imageshack.us/img19/1854/51445300.jpg
A have a class TDMReader which is a buldier of TDMFile objects and I am using Auto Implemented Properties f.e.
public string Name
{
get;
set;
}
public Group[] Groups
{
get;
set;
}
What I want to do is to make setter accessible only for TDMReader methods.
In C++ i could have friends methods to access private variables, in Java I could make them in one packet and so access to fields. I have some ideas but with this auto-implemetation is a bit more complicated to do.
Any ideas with a nite solution?:)
Automatic properties have no bearing on this - the same options are available for automatic properties and "manual" properties. You can restrict the access of the setter like this:
// Setter access only to this type and nested types
public string Name { get; private set; }
// Setter access within the assembly
public Group[] Groups { get; internal set; }
etc
... but you can't do it for a single class (unless that class is nested within the declaring type, in which case private would be fine). There's no namespace-restricted access in .NET or C#.
(It's not entirely clear which class the properties are declared in - if they're TdmReader properties, then just make them private. If they're TdmFile properties, you have the problem described above.)
Like this:
public string Name
{
get;
private set;
}
public Group[] Groups
{
get;
private set;
}
By adding the private keyword, the setters will only be accessible by code in the same class. You can also add internal to make it accessible to code in the same project.
Note that exposing an array as a property is extremely poor design.
Instead, you should expose a Collection<Group> or ReadOnlyCollection<Group>, in the System.Collections.ObjectModel namespace.
I'm making a little program that will crawl my hard drive and present a list of file found in a given drive.
My idea is to have a base File class, and implement Picture.cs, Video.cs and Document.cs classes inherited from the File.cs class.
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SharpLibrary_MediaManager
{
public abstract class File
{
public string name;
public string fileType;
public int size;
public DateTime creationDate;
public DateTime modificationDate;
}
}
Should I declare the short hand code for each attribute like this:
public string name { get; set; }
Any guidance will be helpful. Thank you. :)
Edit:
I mean literally replacing this line:
public string name;
with this line:
public string name { get; set; }
First, "attributes" is not the correct terminolgy here. When you declare a member of a class that has get and/or set defined (formally known as "accessors"), you are defining a property. Properties are a convenient way to expose values of private fields because you can add logic to the getting and setting mechanims.
Second, when you declare a member name as you've done via
public string name { get; set; }
the compiler will expand that into the following:
private string _name;
public string name {
get {
return _name;
}
set {
_name = value;
}
}
That is, the compiler will automatically create a backing field for you and define the accessors. These are called "automatic properties" (for the people)1.
Third, you should never2 publically expose fields. So, if you want to expose the string name as part of your public interface it is better to do it as a property. First, it provides better encapsulation. Second, it can be declared virtual and overridden in dervied classes. Third, you can have custom logic. Fourth, you can have different levels of accessibly between the reading and writing mechanisms on properties but you can not on a field.
Fourth, per accepted naming convetions, public properties should be named with CamelCase so that you should prefer Name instead of name.
1: Sorry, bad joke that I've been waiting a long time to make.
2: Almost never.
You're not describing a short hand syntax for a single item but rather 2 completely different types of members. The get/set version creates a C# Property while the non-get/set version creates a field.
// field
public string name;
// property
public string name {get; set;}
So what you're actually asking here is whether or not you should expose name as a field or a property. The answer is almost certainly property.
If your looking to have these properties, which is what adding the { get; set; } will make the variables, then you should declare the set; part of the property as protected.
So it becomes:
public string name { get; protected set; }
The advantage of this is that you are guaranteeing that the property can only be set by either the base class, or any class that inherits the base class.
As others have suggested, following the C# naming conventions is a good idea and also using properties are highly recommended.
Just to be clear, attributes are means to do declarative programming. They are used to decorate methods, classes, etc. msdn link
If you're asking whether to expose properties rather than public fields, then the answer is Yes.
You should also use PascalCase for the property names rather than camelCase:
public string Name { get; set; }
public string FileType { get; set; }
// etc
As Luke says, all things being equal, properties are preferred to fields.
In addition you may want to change the casing of your fields to match standard C# naming conventions.
Lastly, you might want to avoid the "File" name for your class as you'll probably be using the System.IO namespace which also has a File class. Also, System.IO.FileInfo may already include many of the properties you are planning on creating -- there's no point reinventing the wheel.
I believe another advantage of properties over normal public fields will be ability to override them in the derived class.
class Base
{
public virtual int X
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class Derived : Base
{
public override int X
{
get
{
Console.Write("Derived GET");
return 10;
}
set
{
Console.Write("Derived SET");
}
}
}
Another useful trick that is applicable while using properties is the ability to modify the modifier of the the derived Properties like changing from Public access to Protected.
Hence in many ways its better to use properties in base class to derive.