Lazy<T> and reflection-based initalization - c#

I have a series of classes which initialize themselves when created based on using reflection to read a custom attribute on each property/field. The logic for all that is contained in an Initialize() method which they all call, which exists on the base class they inherit from.
I want to add usages of Lazy<T> to these classes, but I don't want to specify the function(s) in the constructor for each class, because they are "thin" constructors and the heavy lifting is in Initialize(). Conversely, I want to keep type-safety and such so I can't just provide a string of the code to use to initialize the Lazy<T>. The problem is that any usage which refers to the specific properties of the object can't be used in a static context.
Specifically, this is what I want my code to look like in an ideal world:
public class Data : Base
{
public Data(int ID) { Initalize(ID); }
[DataAttr("catId")] // This tells reflection how to initialize this field.
private int categoryID;
[LazyDataAttr((Data d) => new Category(d.categoryID))] // This would tell reflection how to create the Lazy<T> signature
private Lazy<Category> _category;
public Category Category { get { return _category.Value; } }
}
public abstract class Base
{
protected void Initalize(int ID)
{
// Use reflection to look up `ID` and populate all the fields correctly.
// This is where `categoryID` gets its initial value.
// *** This is where _category should be assigned the correct function to use ***
}
}
I would then access this the same way I would if Category were an automatic property (or an explicitly lazy loaded one with an _category == null check)
var data = new Data();
var cat = data.Category;
Is there any way I can pass the type information so that the compiler can check that new category(d.categoryID) is a valid function? It doesn't have to be via an Attribute, but it needs to be something I can see via Reflection and plug in to anything that has a Lazy<T> signature.
As an alternative, I will accept a way to do
private Lazy<Category> _category = (Data d) => new Category(d.categoryID);
This could either avoid reflection altogether, or use it to transform from this form to a form that Lazy<T> can handle.

I ended up using a solution inspired by #Servy's suggestion to get this working. The base class's Initialize() method now ends with:
protected void Initialize()
{
// Rest of code...
InitializeLazyVars();
/* We need do nothing here because instantiating the class object already set up default values. */
foreach (var fi in GetLazyFields())
{
if (fi.GetValue(this) == null)
throw new NotImplementedException("No initialization found for Lazy<T> " + fi.Name + " in class " + this.GetType());
}
}
InitializeLazyVars() is a virtual method that does nothing in the base class, but will need to be overridden in the child classes. If someone introduces a new Lazy<T> and doesn't add it to that method, we'll generate an exception any time we try to initialize the class, which means we'll catch it quickly. And there's only one place they need to be added, no matter how many constructors there are.

Related

C# simplify and perhaps generalize my object cloning method

I've written a method:
class CopyableFloatCommand : FloatCommand
{
public CopyableFloatCommand DeepCopy(LocationHeaderDTO locHeader, string commandId,
List<FloatProductDetailsDTO> recountProuducts)
{
var newCommand = (CopyableFloatCommand)MemberwiseClone();
newCommand.Location = locHeader ?? newCommand.Location;
newCommand.CommandId = commandId ?? newCommand.CommandId;
newCommand.RecountProducts = recountProuducts ?? newCommand.RecountProducts;
return newCommand;
}
}
And am then calling it via:
_tCheckinCommand = _pTCommand.DeepCopy(stagingLocHeadDto, SCICommand,
new List<FloatProductDetailsDTO>(_pTCommand.MoveProducts));
In order to deepcopy an object of type FloatCommand.
As the MemberwiseClone() is a protected method, it's got to be called the way you see above - one cannot parse in a FloatCommand type in the method parameter and call it via fc.MemberwiseClone(), for example. As my method ought to work on a FloatCommand type, I've created a new nested class CopyableFloatCommand which inherits from FloatCommand. DeepCopy method then shallow clones the FloatCommand, casts to the child type and changes some properties as/when needed.
Creating a new class specifically for this purpose seems a bit clunky and I didnt' see a more obvious way of writing it at the time. In terms of lines-of-code, would there be a simpler way of employing a deepcopy such as the above? What about if another class, UserCommand, attempted to deepcopy a User object? UserComand would be a sibling to FloatCommand such that they both inherit from Command. The method would have different parameters parsed for the different types (although I can just remove the parameters altogether and use the instance variables if need be) as the different sub-types have slightly different properties.
In light of this is there a more generic method of writing the DeepCopy method, to be available for access for all the Command types in order to avoid some code duplication, given the above constraints?
Thanks!
I think you're suspecting that the responsibility of cloning the object and mutate its state after it is cloned should be separated - since you're facing with the similar task again (i mean UserCommand).
I would do the following in this situation:
Create a mutation interface:
public interface ICopyCommandMutation
{
void Mutate(Command target);
}
For the sake of extensability i would create the default muate implementation:
public class NoMutation : ICopyCommandMutation
{
public void Mutate(Command target) {}
}
Create the CopyableCommand class and move the DeepCopy() method there (you should also inherit FloatCommand from CopyableCommand):
public CopyableCommand : Command
{
public CopyableCommand DeepCopy(ICopyCommandMutation commandMutation = null)
{
var newCommand = (CopyableCommand)MemberwiseClone();
if (commandMutation == null) commandMutation = new NoMutation();
commandMutation.Mutate(newCommand);
return newCommand;
}
}
Now all the CopyableCommand inheritors can be copied with 'mutations' - you just need to implement the class. For example the FloatCommand 'mutations' from your question:
public class ChangeLocationRecountProducts : ICopyCommandMutation
{
// these fields should be initialized some way (constructor or getter/setters - you decide
LocationHeaderDTO locHeader;
string commandId;
List<FloatProductDetailsDTO> recountProducts;
public void Mutate(Command floatCommand)
{
var fc = floatCommand as FloatCommand;
if (fc == null) { /* handle problems here */ }
fc.Location = locHeader ?? fc.Location;
fc.CommandId = commandId ?? fc.CommandId;
fc.RecountProducts = recountProuducts ?? fc.RecountProducts;
}
}
Here is the usage:
var clrp = new ChangeLocationRecountProducts();
// ... setting up clrp
_tCheckinCommand = _pTCommand.DeepCopy(clrp);
Now if you need to 'mutate' the UserCommand - you can do the separate mutation class for it and keep the mutation logic there. The ability to make different mutations in different sutations (just by defining the separate mutation classes) comes for free.
The only problem i can see here - is that you probably cannot create CopyableCommand and inherit other commands from it (3rd party library?). The solution would be to use Castle dynamic proxy.
I haven't used the Automapper but i suspect that it is doing something similar.
The solution is not 'lines-of-code optimal' - but you would benefit from it if you have to mutate large number of command classes when copying instances.

How to use generics to handle type-specific configurations in an Action<IBuilder<T>>?

I am trying to implement a complex builder to help my testing context. To do that I refactored my code to have a method :
public TestContext Add<T>(Action<IBuilder<T>> configurator) where T : class, new()
{
IBuilder<T> builder = CreateBuilderOf<T>();
configurator(builder);
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
The problem arises when I need to specify the configuration when calling the method :
TestContext.Instance.Add<Person>(personBuilder => ((PersonBuilder)personBuilder).Name("SMITH"));
I need to be able to use type specific methods in the configurator, which are implemented by the concrete builders, such as :
public PersonBuilder : IBuilder<Person>
{
private Person Item;
public PersonBuilder() { Item = new Person(); }
public Name(string mame) { Item.Name = name; }
public Person GetItem() { return Item; }
}
Apparently, passing an Action<PersonBuilder> as an Action<IBuilder<Person>> is not allowed, even though PersonBuilder implements IBuilder<Person>, hence the cast.
I would very much like to either :
Need not to cast inside the lambda but rather at the start of it, e.g.
(PersonBuilder personBuilder) => personBuilder.Name("SMITH"), but that boils down to being an instance of Action<PersonBuilder> and therefore is equally invalid;
Use a function such as BuildSimplePerson(PersonBuilder builder) in Add's argument : Add<Person>(BuildSimplePerson)
I think I can do a type casting through two BuildSimplePersons implementations such as :
private void BuildSimplePerson(IBuilder<Person> builder)
{
BuildSimplePerson(builder as PersonBuilder);
}
private void BuildSimplePerson(PersonBuilder builder)
{
builder.Name("SMITH");
}
But that is not really an elegant solution.
I also realize passing Action<PersonBuilder> as an Action<IBuilder<Person>> is incorrect because we don't know if the argument to that function will truly be a PersonBuilder or any other implementation of IBuilder<Person>.
How can I do better ?
As my comment already states, the problem is that your current code assumes that CreateBuilderOf<T> returns a PersonBuilder but it could actually return anything that implements IBuilder<Person> in which case your cast would fail.
Your code looks like it is generic, but in fact, it is not. You always want to work on the concrete class (PersonBuilder) and not on the general interface IBuilder<Person>.
My understanding is, that you want one generic Add<T> method to avoid having to repeat that code inside it for each type.
Here is my approach:
public TestContext Add<T>(IBuilder<T> builder) where T : class, new()
{
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
You would call it like this:
TestContext.Instance.Add<Person>(CreatePersonBuilder().Name("SMITH"));
Obviously, you would need to have a CreateXBuilder method for each type that you want to be able to add. However, I think you already have this at least implicitly, because I would assume that your CreateBuilderOf<T> method is one huge switch statement anyway.
If you don't want to create such methods, another approach to get the builder would be a generic method like so:
CreateBuilder<PersonBuilder>()
But really, this is actually nothing more than a new PersonBuilder(), so you actually could simply go with
TestContext.Instance.Add<Person>(new PersonBuilder().Name("SMITH"));
The Configure method would be very similar:
TestContext.Instance.Configure<Person>(id, p => new PersonBuilder(p).Name("SMITH"));
This would pass the ID, which the Configure method would use to look up the object, which in turn is passed to the callback. So the second parameter of Configure would not be a Action<IBuilder<T>> but an Action<T>.
This approach has another advantage over your existing code:
Your existing code assumes not just that PersonBuilder will be the implementation used for IBuilder<Person>. No, your code also assumes that it has a constructor without parameters and one which takes a Person. These assumptions are impossible for the compiler to verify.
With the code I showed above, a builder implementation could take additional parameters without problems and the compiler would verify that everything is alright.

C# Activator.CreateInstance generic instance getting lost

FYI: the verbose preamble is to help explain why I am using Activator.CreateInstance. I have a number of entities (objects corresponding to database column information) that are "contained" in multiple databases, each of which has a different table/column setup. So I am able to retrieve an entity from each database, but the way I retrieve it is different per database. The database type is not known till runtime and could vary throughout execution. I have created the following setup:
First define the query operations each entity should support and each entity reader should support these operations.
public abstract class Operations<T> {
public delegate T findDelegate(int id);
public findDelegate find;
}
// there are many of these N=1,2,..., but here is one
// use abstract class since implementation of queries should be done by handlers
public class EntityNReader : Operations<EntityN> {
public Reader();
}
Define an interface for "Handler" classes, i.e. these classes implement the query operations listed above.
public interface IHandler<T> {
public string find(int id);
}
// there are many of these N,M=1,2..., but here is one
// use of interface is to force handlers to implement all query types
public class EntityNHandlerForDbTypeM : IHandler<EntityN> {
public string find(int id) {/*whatever*/}
}
This allows the developers to create a single class for handling EntityN query operations for DbTypeM. Now, create a Database class that contains the reader objects and binds the handler methods to the reader delegates.
public class Database {
// there are many of these, but here is one
public EntityNReader EntitiesN;
public Database(string dbType) {
// this is called for each EntityNReader
bindHandlers<Reader, TypeN>(MyReader, dbType);
// ...
// nullreferenceexception
EntitiesN.find(0);
}
// this is a factory that also performs late binding
private void bindHandlers<T,K>(T reader, string dbTypeM)
where T: Operations<K>, new()
{
// create instance of EntityNReader
r = (T)Activator.CreateInstance(typeof(T));
// r != null
// create instance of handler
IHandler<K> h = (IHandler<K>)(Activator.CreateInstance(
Type.GetType("namespace.to.EntityNHandlerForDbTypeM"),
new object[] { this }
));
// bind delegates
r.find = h.find;
}
}
As you can see in Databases constructor, the way the code is written now, I get a NullReferenceException even though instance r of EntityNReader is created and (verified to be) not null.
However, if I instantiate EntitiesN where it is declared in Database instead of within bindHandlers, the code compiles and everything works. The reason I don't just do this is that (subsequently) I would like to conditionally create readers/handlers inside of bindHandlers at the time the Database class is instantiated.
What is happening here? Link to actual code if necessary.
P.S. I am relatively new to programming, so I am open to hearing how an experience developer might design this component (especially if I am heading down the wrong path).
I realize your code was just samples, but I spotted this right off the bat...
if (supports[typeof(Entity1).Name]) { bindHandlers<Entity1Reader, Entity1>(Entities1, CamaDbType); }
if (supports[typeof(Entity2).Name]) { bindHandlers<Entity1Reader, Entity1>(Entities1, CamaDbType); }
Is it possible that you have a simple copy/paste mistake? Notice that Entities1 is passed in for both bindHandlers calls.

Efficiently determine type

I'm faced with the prospect of using a factory method like below to effect setter based DI (because Entity Framework prevents me from using constructor based DI). So when an object is materialized in EF I call the method below to do the setter DI.
public void AttachKeyHolder(ILocalizableEntity localizableEntity)
{
var ft = (localizableEntity as FeeType);
if (ft != null)
{
localizableEntity.KeyHolder = new FeeTypeKeyHolder();
return;
}
var other = (localizableEntity as OtherType);
if (other != null)
{
localizableEntity.KeyHolder = new OtherTypeKeyHolder();
return;
}
// And on and on and on for every applicable type
}
I don't like this because it becomes a n-based problem whereby if I have 20 types that need this setter injection then whichever one is type checked in 20th place takes 20 times the amount of time to check as the first type check and since Im doing this every single time an object is materialized in EF it will likely not scale.
So Im looking for a better algorithm. The previous "solution" was to just assign the appropriate KeyHolder in the constructor of the associated object as below:
public FeeType()
{
this.KeyHolder = new FeeTypeKeyHolder();
}
This still seems like the most runtime efficient solution and one I'm still leaning very strongly towards regardless of testability due to potentially massive effect setter based DI will likely have with the above factory method. I'd really likely to decouple these classes but not at the expense of the scalability for this web application.
You can mark properties you need to set via DI with your attribute, like [Inject], and then in desired place (like constructor) call helper method like MyHelper.InjectProperties(this). In helper you can get attributes with [Inject] and resolve their values directly from constructor.
Most of IoC/DI frameworks supports property injection in a performance effective way, so in best of worlds you won't need to implement it by yourself.
First of all, are you sure this is going to have such a bad performance impact. I would doubt so.
Anyway, you can use Visitor patter to implement double dispatch, so instead of 20 test for type of the object, you invoke 2 virtual methods, that is two lookups in virtual methods tables, which might be faster than 20 tests, however there is the overhead of two indirect function calls, stack frame allocation for each of them, etc. But again, do we really want to go so deep in case of a C# project with Entity Framework?
Example:
class Visitor {
public virtual void Visit(FeeType f) {}
public virtual void Visit(OtherType t) {}
}
class abstract BaseType { public abstract void Accept(Visitor v); }
class FeeType : BaseType {
public override void Accept(Visitor v) { v.Visit(this); }
}
class OtherType : BaseType {
public override void Accept(Visitor v) { v.Visit(this); }
}
class DIVisitor : Visitor {
public virtual void Visit(FeeType f) { f.KeyHolder = new ... }
public virtual void Visit(OtherType t) { t.KeyHolder = new ... }
}
public void AttachKeyHolder(ILocalizableEntity localizableEntity)
{
var ft = (localizableEntity as TypeBase);
ft.Accept(new DIVisitor());
}
You can also implement the lookup for the correct method based on type through hashing.
HashMap<Type, Action<BaseType>> actions;
actions.Add(typeof(FeeType), x => { ((FreeType)x).KeyHolder = new .... });
...
actions[ft.GetType()].Invoke(ft);

Restricting class method access to one other class

Greetings.
I have two classes, 'Database' and 'Group.' I want to be able to create instances of 'Group' and call methods on those instances from within 'Database' and to be able to distribute 'Group' instance references publicly. However, I do not want to provide public access to the constructor or other methods in 'Group.'
I originally thought that I could achieve this access restriction by making 'Group' a private inner class of 'Database,' but I discovered that I couldn't publicly distribute references to 'Group' if it was private. Also, my attempts at making 'Group' a public inner class failed, because if its methods were all private, 'Database' couldn't access them, and if they were public, access was possible beyond 'Database.'
I am looking for a best-practice technique for solving or circumventing this problem. Maybe I missed a necessary keyword somewhere? Nothing I have found thus far in my research has indicated that C# permits this granularity of control. I found a messy way to get around the problem, as I've provided below in code. Its essence is this: before every call in 'Database' to a method in 'Group,' set a field in 'Database,' publicly readable but only privately settable, that 'Group''s methods all check in their creating instances of 'Database' before performing their intended operations. When reading the field (via a public method in 'Database,') the field is reset, preventing any further method calls on 'Group' until 'Database' sets the field again.
public class Database {
// Field; true if Database has just authorized a method call to a %Group.
private bool group_isNextCallAuthorized = false;
// Invoked before every method call to a %Group.
private void Group_AuthorizeNextCall() {
group_isNextCallAuthorized = true;
}
// Method, ordinarily called from %Group, that checks its creating %Database
// that the %Database itself authorized the method call on the %Group. It
// automatically resets the authorization to false to prepare for the next,
// perhaps unauthorized, method call.
public bool Group_IsNextCallAuthorized() {
bool previousValue = group_isNextCallAuthorized;
group_isNextCallAuthorized = false;
return previousValue;
}
// Constructor; creates a demo %Group.
public Database() {
// Create a %Group, first authorizing the action.
Group_AuthorizeNextCall();
Group group = Group.Create(this);
// Call some method on the group
Group_AuthorizeNextCall();
group.SomeGroupMethod();
}
}
public class Group {
// Field; refers to the %Database that created this %Group instance.
private Database db;
// Generates an instance of %Group, requiring the creating %Database as an
// argument. After checking that the %Database %db isn't null, it verifies
// that %db actually requests and authorized this %Group's creation via the
// %Group_IsNextCallAuthorized(.) method provided by %Database.
public static Group Create(Database db) {
// It will not create a dud instance of %Group; it will throw an exception
// instead.
if ((db == null) || !db.Group_IsNextCallAuthorized())
throw new System.Exception("Unauthorized access.");
return new Group(db);
}
// This constructor is referenced internally by static %Create(.) as above.
private Group(Database db) {
this.db = db;
}
// This is an arbitrary method showing that it must check that the %Database
// that created this %Group authorized this method call before it will
// perform its intended function.
public void SomeGroupMethod() {
if (!db.Group_IsNextCallAuthorized())
throw new System.Exception("Unauthorized access.");
// intended functionality...
}
}
One option would be to expose an interface IGroup to the outside parts of your code. This interface would only have getters on the properties, whatever methods you want accessible, etc. Then Database would operate on the Group class, having full access to all properties/methods, and returning IGroup
You can use nested class approach. Probably not the most eligant one since tightly coupled but will do the trick.
public class DataBase
{
private class Group
{
private Group() {}
}
private Group group = null;
public DataBase()
{
this.group = new Group();
}
public Group
{
get
{
return this.group;
}
}
To express this visibility using C# access rules, you need to reverse the class nesting: make Database a nested class inside Group, so it can access the private bits of Group.

Categories

Resources