Dynamic declaration in attribute property

10

As part of an ORM microplatform I'm developing, I'm defining a generic class that implements exclusively tight coupling (1 record x 1 object).

public class Course : MicroEntity<Course>
{
    public string fullname { get; set; }
    public string shortname { get; set; }
    public string summary { get; set; }
    public string format { get; set; }
    [...]
}

To define the behavior of this class, I have an Attribute that contains all the initialization characteristics:

[MicroEntity(
    TableName = "mdl_course",
    IdentifierColumnName = "ID",
    IsReadOnly = true,
    UseDistributedCaching = true)]
public class Course : MicroEntity<Course>
{
    public string fullname { get; set; }
    public string shortname { get; set; }
    public string summary { get; set; }
    public string format { get; set; }
    [...]
}

Recently I've implemented a DatabaseAdapter engine to allow agnostic connection to different databases:

public abstract class BaseAdapter
{
    internal abstract void CheckDatabaseEntities<T>() where T : MicroEntity<T>;
    internal abstract void SetSqlStatements<T>() where T : MicroEntity<T>;
    internal abstract void SetConnectionString<T>() where T : MicroEntity<T>;
    internal abstract void RenderSchemaMicroEntityNames<T>() where T : MicroEntity<T>;
    internal abstract BaseDynamicParameters Parameters<T>(object obj) where T : MicroEntity<T>;
    internal abstract DbConnection Connection(string connectionString);
}

From there, I declare Adapters for different banks. I currently have adapters for Oracle and MySql.

Question

I'd like to be able to declare the adapter as an Attribute property:

[MicroEntity(
    TableName = "mdl_course",
    IdentifierColumnName = "ID",
    IsReadOnly = true,
    Adapter = new InternalAdapters.MySql.Adapter();
    UseDistributedCaching = true)]
public class Course : MicroEntity<Course>
{
    [...]

However, new() is not allowed. Which model would best meet this type of behavior?

    
asked by anonymous 06.10.2015 / 19:56

2 answers

4

The problem is that attributes do not support dynamic object initialization. There are two alternatives:

1. Mark attribute with adapter type

[MicroEntity(
    TableName = "mdl_course",
    IdentifierColumnName = "ID",
    IsReadOnly = true,
    Adapter = typeof(InternalAdapters.MySql.Adapter),
    UseDistributedCaching = true)]

2. Mark the attribute with an enumeration

[MicroEntity(
    TableName = "mdl_course",
    IdentifierColumnName = "ID",
    IsReadOnly = true,
    Adapter = Adapter.MySql,
    UseDistributedCaching = true)]

I am positively in favor of the first, especially since you virtually have no limits to inject new adapters into the application when this is desired.

When reading the attribute, the initialization would be quite simple:

var course = new Course();
var atributoMicroEntity = course.GetType().GetAttribute<MicroEntityAttribute>();
if (atributoMicroEntity != null) 
{
    var adaptador = Activator.CreateInstance(atributoMicroEntity.Adapter);
}
    
06.10.2015 / 20:43
6

I've seen this problem resolved using a Type (I can not remember where, but I'm sure I've seen more than once).

public class MicroEntityAttribute : Attribute
{
    public Type Adapter { get; set; }
}

[MicroEntity(Adapter = typeof(InternalAdapters.MySql.Adapter))]
public class SomeClass {}

The expression new Class() is not a constant, but typeof(Class) is - and therefore can be used to initialize an attribute.

The attribute interpreter must then initialize an adapter instance using Activator ", and throwing an exception if you do not have a public constructor without parameters.

    
06.10.2015 / 20:45