Add Methods to Castle DictionaryAdapterFactory Interface - c#

I'm following the tutorial on this site which talks about using the Castle DictionaryAdapterFactory and an interface to access an applications app.setting keys without using strings throughout your code.
The way it works is you define an Interface that has the key names for your app.settings
public interface ISettings
{
string dog { get; }
string cat { get; }
}
Then use the DictionaryAdapterFactory to do the coding between the interface and your app.settings dictionary.
var factory = new DictionaryAdapterFactory();
var settings = factory.GetAdapter<ISettings>(ConfigurationManager.AppSettings);
Now you can access the values like this:
settings.dog
settings.cat
My question is, is it possible to have something more than a complicated than a simple getter. For example, can I tell DictionaryAdapterFactory to use a decryption method on the value of one of the keys and then return that instead of the key value?
I'm assuming that this is not possible since you can't define methods in an interface, but wanted to see if there was another way that I was missing.

You can use a wrapper class to wrap your interface with a class that implements custom methods.
You add [AppSettingWrapper] over your interface:
[AppSettingWrapper]
public interface ISettings
{
string dog { get; }
string cat { get; }
}
The AppSettingWrapper class is defined in the class below and lets you do what you want in the getter and setting.
public class AppSettingWrapperAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder, IPropertyDescriptorInitializer, IDictionaryPropertyGetter
{
public string GetKey(IDictionaryAdapter dictionaryAdapter, string key, PropertyDescriptor property)
{
return key;
}
public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue, PropertyDescriptor property, bool ifExists)
{
return storedValue;
}
public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
{
propertyDescriptor.Fetch = true;
}
}
Most of this solution comes from https://gist.github.com/kkozmic/7858f4e666df223e7fc4.

Related

Inner class within Interface in C#

The following question shows how to implement an interface that contains a class in java:
inner class within Interface
The code in Java is:
public interface A {
class B {
}
}
I was hoping the same thing was possible in C#, though I haven't yet been able to get anything working.
For reference, I have a class which makes lookups of key values, but the keys aren't named in a way that makes them easy to understand. I'd like to have a compile time lookup for keys, so the interface would be something like:
interface Lookup {
class Keys {
string SomeKey() => "0"
}
}
Which means I suppose I have two questions:
Is it possible to have an interface containing a class?
Is there a better way of having a lookup between two strings (or any other values) that I can reference reliably at compile time?
Simply put no you can't have a class inside an interface.
From your comments you are talking about having a restricted list of available strings for the keys so I'm wondering if you are in fact not looking for a string/string lookup but just want a convenient way of referencing a list of fixed strings. So a class with constants is all you need:
public static class Strings
{
public const string AString = "A";
public const string BString = "B";
public const string CString = "C";
}
Accessed like this:
var s = Strings.AString;
You cannot have an class within an interface in C#. Interfaces are very simple in C#, and only provide a contract of functionality.
If you want to have a mapping between two strings, a Dictionary<string, string> may be of use to you.
An interface can't itself have any instance data. It's implementation however can have any instance data it requires.
For example, a random example that might give you some insight:
public class SomeClass
{
public string Key {get; set;}
}
public interface ISomeInterface
{
string Value { get; set; }
SomeClass SomeClass { get; set;}
}
public class SomeInterfaceImplementation : ISomeInterface
{
public SomeInterfaceImplementation()
{
SomeClass = new SomeClass()
{
Key = "ABC"
};
}
public string Value { get; set; }
public SomeClass SomeClass { get; set; }
}
public class Program
{
public static void Main()
{
var example = new SomeInterfaceImplementation()
{
Value = "A value",
} as ISomeInterface;
Console.WriteLine($"{example.SomeClass.Key} has value '{example.Value}'");
}
}
In the example, the default constructor "generates" a key of ABC. We could implement this any way your logic requires. But you also have a contract that requires "SomeClass" and it's key is present.
Anywhere you want to use the contract, just accept the Interface and not an implementation class.
Additionally, feel free to play with the fiddle:
Most of the answers under this question are no longer true.
Since C# 8.0, when default interface methods were added, it is possible for an interface to have member declaration that declare for example nested type.
The following code is correct for C# 8.0:
public interface IA
{
class B
{
}
}

C# generic method for multiple classes

I tried to search for solutions, but my problem is I don't even know what terms to use. Generics, Delegates, LINQ, Reflection, and Abstract ideas could be part of the solution, but my "Google-fu" isn't turning up the right answer.
Question:
I have multiple classes (ClassA, ClassB, ClassC) that all have the same 2-3 properties DoThisA, DoThisB, DoThisC.
The way the code works is that I always want to do the same code to set DoThisA, DoThisB, and DoThisC when I process each of the classes.
For example, to simplify, the logic will always be:
{some computations to set string currentValueImProcessing to something}
if (xyz) [ClassA|B|C].DoThisA = currentValueImProcessing
else [ClassA|B|C].DoThisB = currentValueImProcessing
I don't want to write those same statements over and over, so how do I just send a reference to the class (A,B,C) to a method to do the logic?
If it was written correctly each of ClassA, ClassB, and ClassC would have implemented some generic class and I could use that, but I cannot. Each of the classes are independent but have the same named properties.
Any guidance on concepts/code?
Thanks!
Create an interface for your properties:
internal interface IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
Then, make your classes implement it:
public class ClassA : IDoThis
{
public string DoThisA { get; set; }
public string DoThisB { get; set; }
public string DoThisC { get; set; }
}
public class ClassB : IDoThis
{
// Same properties
}
public class ClassC : IDoThis
{
// Same properties
}
This, way, you'll be able to create a static initializer method somewhere:
internal static class MyClassesExtensions
{
public static void InitTheStuff(this IDoThis obj)
{
// Do something here, for example:
if (String.IsNullOrEmpty(obj.DoThisA))
obj.DoThisA = "foo";
else
obj.DoThisB = obj.DoThisC;
}
}
And then you can just call this.InitTheStuff() anywhere from ClassA, ClassB and ClassC.
you can either use reflection or you can use dynamic (dynamic will use reflection for you)
dynamic obj = new ClassA();
obj.DoTHisA();
is how to do it with dynamic
I am assuming that you are talking about classes that you intend to instantiate. If DoThisA,B,C are static methods then you must use reflection
NOTE - if you can change the classes then add an interface as others have suggested, or even a common base class
The reflection one looks like this
var type = obj.GetType(); // obj is ClassX object
var method = type.GetMethod("DoTHisA");
method.Invoke(obj);
I have not checked this - so the syntax might be a bit off - but this is the basic mechanics of reflection method calling. YOu need to get fancier if there are multiple methods with the same name, if the methods takses params etc
There are at least four options open to you - maybe more.
Create an interface, which is implemented by all of your classes and that includes the common methods.
Create a base class from which all classes inherit. The common functionality can then be implemented in the base class. If the implementation differs depending on the clases, but you can define common signatures for the methods, make your base class an the common funtionality abstract. You then can implement the actual functionality in each of your classes.
Use a dynamic object as in #pm100's solution.
Use reflection to access the common functionality.
As a guidance methods 1. and 2. are to be preferred, as they allow your code to be checked on compile time. If, however, you do not have control over the classes that contain the common functionality - for example you do not have access to the source code or you are permitted to make changes to the code - you can use the other two methods.
If you'd ask me which of the two I would prefer, I guess that I would go for 3. over 4. But this is personal preference.
Prob you are talking about inheritance.
For your task you need a base abstract class with general properties:
public abstract class Base
{
public bool DoThisA { get; set; }
public bool DoThisB { get; set; }
}
and child classes:
public class A : Base { }
public class B : Base { }
public class C : Base { }
After that you can create a method which will accept object of type Base
public void Do(Base b, bool xyz, bool currentValueImProcessing)
{
if (xyz)
{
b.DoThisA = currentValueImProcessing;
}
else
{
b.DoThisB = currentValueImProcessing;
}
}
There are already many methods provided here, so just for the sake of completeness... Here's some runtime code generation:
public class ClassA
{
public string DoThisA { get; set; }
public int DoThisB { get; set; }
public bool DoThisC { get; set; }
public void Init()
{
// You can call this from anywhere, even from an unrelated class
MyClassInitializer<ClassA>.Init(this);
}
}
public static class MyClassInitializer<T>
{
// Create the getters/setters you need, and make sure they're static.
private static readonly Func<T, string> _getA = BuildGetter<string>("DoThisA");
private static readonly Action<T, string> _setA = BuildSetter<string>("DoThisA");
private static readonly Func<T, int> _getB = BuildGetter<int>("DoThisB");
private static readonly Action<T, int> _setB = BuildSetter<int>("DoThisB");
private static readonly Func<T, bool> _getC = BuildGetter<bool>("DoThisC");
private static readonly Action<T, bool> _setC = BuildSetter<bool>("DoThisC");
private static Func<T, TValue> BuildGetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
return Expression.Lambda<Func<T, TValue>>(Expression.Property(obj, name), obj).Compile();
}
private static Action<T, TValue> BuildSetter<TValue>(string name)
{
var obj = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(TValue));
return Expression.Lambda<Action<T, TValue>>(Expression.Assign(Expression.Property(obj, name), value), obj, value).Compile();
}
public static void Init(T obj)
{
// Here's your custom initialization method
if (_getA(obj) == "Foo")
_setB(obj, 42);
else
_setC(obj, true);
}
}
Not necessarily the easiest one to grasp, but this should be much faster than using dynamic or reflection. That said, if you don't need the speed, stick with dynamic as it's easier.

How to not violating the OCP when you want to choose between different classes which are inherited from an Interface?

I have an Interface lets say ISendOut which I've inherited two different classes from it
for example TransferViaSerialPort and TransferViaWirelessModule (I mean implement this Interface in these two classes). How can I design my software to both giving the ability to the user to choose (IN THE UI) between the methods of sending his/her data out via SerialPort or WirelessModule and not violate the OCP? Because if I want to have a "Switch Case" or an "If/Else" statement I will Violate the OCP.
You need to use the Factory Pattern. And to make the Factory Pattern dynamic you can use Reflection and to show the Types of your Classes in the UI which are Implemented from ISendOut you can use Custom Attributes or other methods like using a Dictionary.
[System.AttributeUsage(System.AttributeTargets.Class)]
public class DisplayNameAttribute : Attribute
{
public DisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public interface ISendOut
{
void Send(string data);
}
[DisplayName("Wireless")]
public class WirelessSendOut : ISendOut
{
public void Send(string data)
{
MessageBox.Show("data sent through wireless.");
}
}
[DisplayName("Serial")]
public class SerialSendOut : ISendOut
{
public void Send(string data)
{
MessageBox.Show("data sent through serial port.");
}
}
public static class SendOutFactory
{
public static ISendOut CreateSendOut(string typeName)
{
var types = Assembly.GetExecutingAssembly().GetTypes();
var sendOutType = types.First(x => (typeof(ISendOut)).IsAssignableFrom(x) && x.Name == typeName);
return (ISendOut) Activator.CreateInstance(sendOutType);
}
}
public static class SendOutDiscovery
{
public static IEnumerable<NameType> Discover()
{
var types = Assembly.GetExecutingAssembly().GetTypes();
var sendOutTypes = types.Where(x => x != typeof(ISendOut) && (typeof(ISendOut)).IsAssignableFrom(x));
return sendOutTypes.Select(type => GetNameType(type)).ToList();
}
private static NameType GetNameType(Type type)
{
var nameType = new NameType
{
DisplayName = GetDisplayName(type),
TypeName = type.Name
};
return nameType;
}
private static string GetDisplayName(Type type)
{
return ((DisplayNameAttribute)type.GetCustomAttributes(typeof (DisplayNameAttribute), false).First()).DisplayName;
}
}
public class NameType //for binding in UI
{
public string DisplayName { get; set; }
public string TypeName { get; set; }
}
public class SendOutViewModel //sample using in wpf (window contains a combobox)
{
public SendOutViewModel()
{
SendTypes = new ObservableCollection<NameType>(SendOutDiscovery.Discover());
}
public NameType SelectedSendType { get; set; } //bind to selected item in combobox
public ObservableCollection<NameType> SendTypes { get; private set; } //bind to item source of combo
public string Data { get; set; } //data to be sent
public void Send()
{
ISendOut sendOut = SendOutFactory.CreateSendOut(SelectedSendType.TypeName);
sendOut.Send(Data);
}
}
Later I add UsbSendOut without modifying existing code (so not Breaking the OCP)
[DisplayName("Usb")]
public class UsbSendOut : ISendOut
{
public void Send(string data)
{
MessageBox.Show("data sent through usb.");
}
}
You pass your implementation of ISendOut as a parameter, e.g. to a constructor, and let C#'s dynamic dispatch do the "switch case", as you've put it.
That's why interfaces are so useful: you have an indirection and can do dependency injection to meet OCP.
Create a UserConfiguredCommunicationModule class (favor composition over inheritance)
public class UserConfiguredCommunicationModule : ISendOut
{
public UserConfiguredUserModule(SerialPort serial, WirelessModule wireless)
{}
public void Send(string data)
{
if (UserIdentity.Current.PrefersSerial)
serial.Send(data);
else
wireless.Send(data);
}
}
Using that implementation will prevent you from breaking OCP (although the class itself violates OCP, but that can easily be fixed by using a factory in it).
Update
you know what's wrong with that? I want to give the ability to the user to choose the method of Sending Out the Data in the UI. Now imagine that we will have much more methods of Sending Out i.e. Sending Out Via Infrared or ... so by letting the user choose between different methods, I have to have an if statement in my UI which it will violate the OCP. Because every new type of Sending Out will force me to have new if/else condition
My approach move the violation of OCP into one class only, instead of every single place where the ISendOut interface is used.
I also mentioned factory, in which I mean the factory pattern (neither abstract factory or factory method). You can use it to map between configuration strings and the concrete classes and use that factory inside of UserConfiguredCommunicationModule to create the proper ISendOut implementation.
You can also use service locator pattern within the UserConfiguredCommunicationModule to resolve the correct implementation.
That point is no matter what you choose, you need a UserConfiguredCommunicationModule similar class to encapsulate the selection process.
Check out the strategy pattern
https://en.wikipedia.org/wiki/Strategy_pattern
http://www.dofactory.com/Patterns/PatternStrategy.aspx#_self1

Dynamic implementation of an Interface

Suppose I have an Interface with some properties:
public interface IDummy
{
string First {get;set;}
string Second {get;set;}
string Third {get;set;}
string Fourth {get;set;}
}
Now, I have a class which implements that interface:
public class DummyClass: IDummy
{
// ...
}
Is it possible, not to implement the interface properties explicitly and instead use DynamicObject? For example:
public class DummyClass: DynamicObject, IDummy
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Get the value from a Config file or SQLite db or something
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Get the value to a Config file or SQLite db or something
}
}
I am just curious if this is possible or not?
Thanks.
No, this is not possible.
If you are implementing an interface, you need to implement all of its members. C# is still a statically typed language, after all.
When you say a type implements an interface, you are saying it conforms to its contract. Not implementing all of the members means that you are not complying with the contract.
The compiler would see your code and will not assume that you have implemented the contract correctly (in a dynamic fashion) - it will fail to compile.
No, basically. An interface is for static typing; to satisfy an interface your type must actually provide a regular (non-dynamic) implementation. You could not claim to implement it (IDummy), and detect the names, but that could relate to any interface that uses those same names, not just IDummy.
You could make a wrapper.
class DummyWrapper : IDummy
{
private readonly DynamicObject _wrapped;
public DummyWrapper(DynamicObject wrapped)
{
_wrapped = wrapped;
}
string First
{
get { return _wrapped.First; }
set { _wrapped.First = value; }
}
string Second
{
get { return _wrapped.Second; }
set { _wrapped.Second = value; }
}
string Third
{
get { return _wrapped.Third; }
set { _wrapped.Third = value; }
}
string Fourth
{
get { return _wrapped.Fourth; }
set { _wrapped.Fourth = value; }
}
}
You might also be interested in these questions:
Automatically creating a wrapper to implement an interface
Dynamically implementing an interface in .NET 4.0 (C#)

What is an alternative to having static abstract methods?

I'm having some problems trying to figure out how to solve a problem without being able to have static method in an abstract class or interface. Consider the following code. I have many Wizards that inherit from AbsWizard. Each wizard has a method GetMagic(string spell) that only returns magic for certain magic words, yet all instances of a specific type of wizard respond to the same set of magic words.
public abstract class AbsWizard
{
public abstract Magic GetMagic(String magicword);
public abstract string[] GetAvalibleSpells();
}
public class WhiteWizard : AbsWizard
{
public override Magic GetMagic(string magicword)
{
//returns some magic based on the magic word
}
public override string[] GetAvalibleSpells()
{
string[] spells = {"booblah","zoombar"};
return spells;
}
}
public class BlackWizard : AbsWizard
{
public override Magic GetMagic(string magicword)
{
//returns some magic based on the magic word
}
public override string[] GetAvalibleSpells()
{
string[] spells = { "zoogle", "xclondon" };
return spells;
}
}
I want the user to be able to first choose the type of wizard, and then be presented with a list of the spells that type of wizard can cast. Then when they choose a spell the program will find all, if any, existing wizards of the selected type and have them cast the selected spell. All wizards of a specific type will always have the same available spells, and I need a way to determine the spells a specific type of wizard can cast with out actually having access to an instance of the selected type of wizard.
In addition I don't want to have to depend on a separate list of possible wizard types or spells. Instead I would rather just infer everything through GetAvalibleSpells() and reflection. For example I plan to cast magic as follows:
public static void CastMagic()
{
Type[] types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes();
List<Type> wizardTypes = new List<Type>();
List<string> avalibleSpells = new List<string>();
Type selectedWizardType;
string selectedSpell;
foreach (Type t in types)
{
if (typeof(AbsWizard).IsAssignableFrom(t))
{
wizardTypes.Add(t);
}
}
//Allow user to pick a wizard type (assign a value to selectedWizardType)
//find the spells the selected type of wizard can cast (populate availibleSpells)
//Alow user to pick the spell (assign a value to selectedSpell)
//Find all instances, if any exsist, of wizards of type selectedWizardType and call GetMagic(selectedSpell);
}
I think this is very bad style. You write the code, so you should know what wizard-classes you have in there. It's very bad style (and slow!) to run through all types via reflection and check if they derive from AbsWizard.
The Managed Extensibility Framework (available through codeplex for pre-.NET-4.0, or built-in .NET 4.0 in the System.ComponentModel.Composition namespace) was built for this. Say you have a service that can ask a user to select a wizard and then create it. It uses a wizard provider to create the wizards, and needs to know the name and available spells (metadata) for the wizards that a provider creates. You might use interfaces like these:
namespace Wizardry
{
using System.Collections.Generic;
public interface IWizardProvider
{
IWizard CreateWizard();
}
public interface IWizard
{
IMagic GetMagic(string magicWord);
}
public interface IWizardProviderMetadata
{
string Name { get; }
IEnumerable<string> Spells { get; }
}
}
The wizard creation service imports the available wizard providers, selects one through some mechanism (user feedback in your case), and uses the provider to create the wizard.
namespace Wizardry
{
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
public class UserWizardCreationService
{
[Import]
private IEnumerable<Lazy<IWizardProvider, IWizardProviderMetadata>> WizardProviders { get; set; }
public IWizard CreateWizard()
{
IWizard wizard = null;
Lazy<IWizardProvider, IWizardProviderMetadata> lazyWizardProvider = null;
IWizardProvider wizardProvider = null;
// example 1: get a provider that can create a "White Wizard"
lazyWizardProvider = WizardProviders.FirstOrDefault(provider => provider.Metadata.Name == "White Wizard");
if (lazyWizardProvider != null)
wizardProvider = lazyWizardProvider.Value;
// example 2: get a provider that can create a wizard that can cast the "booblah" spell
lazyWizardProvider = WizardProviders.FirstOrDefault(provider => provider.Metadata.Spells.Contains("booblah"));
if (lazyWizardProvider != null)
wizardProvider = lazyWizardProvider.Value;
// finally, for whatever wizard provider we have, use it to create a wizard
if (wizardProvider != null)
wizard = wizardProvider.CreateWizard();
return wizard;
}
}
}
You can then create and export an arbitrary number of wizard providers with spells, and the creation service will be able to find them:
namespace Wizardry
{
using System.ComponentModel.Composition;
[Export(typeof(IWizardProvider))]
[Name("White Wizard")]
[Spells("booblah", "zoombar")]
public class WhiteWizardProvider : IWizardProvider
{
public IWizard CreateWizard()
{
return new WhiteWizard();
}
}
[Export(typeof(IWizardProvider))]
[Name("White Wizard")]
[Spells("zoogle", "xclondon")]
public class BlackWizardProvider : IWizardProvider
{
public IWizard CreateWizard()
{
return new BlackWizard();
}
}
}
Of course you'll need to implement the wizards as well.
namespace Wizardry
{
using System;
public class WhiteWizard : IWizard
{
public IMagic GetMagic(string magicWord)
{
throw new NotImplementedException();
}
}
public class BlackWizard : IWizard
{
public IMagic GetMagic(string magicWord)
{
throw new NotImplementedException();
}
}
}
To keep things clean, this code uses a custom NameAttribute and SpellsAttribute as a much cleaner form of exporting metadata than ExportMetadataAttribute:
namespace Wizardry
{
using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public abstract class MultipleBaseMetadataAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public abstract class SingletonBaseMetadataAttribute : Attribute
{
}
public sealed class NameAttribute : SingletonBaseMetadataAttribute
{
public NameAttribute(string value) { this.Name = value; }
public string Name { get; private set; }
}
public sealed class SpellsAttribute : MultipleBaseMetadataAttribute
{
public SpellsAttribute(params string[] value) { this.Spells = value; }
public string[] Spells { get; private set; }
}
}
Add another level of indirection. The GetAvailableSpells method isn't really an instance method, since it's the same for all instances. As you pointed you, you can't have an abstract static method, so instead move the type-specific stuff into an instance-based class factory. In the example below, AvailableSpells is a method of the MagicSchool abstract class, which has concrete subclasses BlackMagic, WhiteMagic, etc. The Wizard also has sub-types, but every Wizard can return the MagicSchool that it belongs to, giving you a type-safe, type-independent way to find out what the spells for any given Wizard object are without separate tables or code duplication.
public abstract class MagicSchool
{
public abstract string[] AvailableSpells { get; }
public abstract Wizard CreateWizard();
}
public abstract class Wizard
{
protected Wizard(MagicSchool school)
{
School = school;
}
public abstract Cast(string spell);
MagicSchool School
{
public get;
protected set;
}
}
public class BlackMagic : MagicSchool
{
public override AvailableSpells
{
get
{
return new string[] { "zoogle", "xclondon" };
}
}
public override Wizard CreateWizard()
{
return new BlackWizard(this);
}
}
public class BlackWizard : Wizard
{
public BlackWizard(BlackMagic school)
: base(school)
{
// etc
}
public override Cast(string spell)
{
// etc.
}
}
// continue for other wizard types
First, you should really consider whether you can't bend the rules of not using instances of Wizards to discover their available spells. I find that the prototype pattern can actually be quite useful for this sort of thing.
However, if you really can't do that, you can use nested classes and reflection to discover the available spells that a particular concrete AbsWizard-derivative can cast. Here's an example:
public abstract class AbsWizard
{
public abstract Magic GetMagic(String magicword);
public abstract string[] GetAvalibleSpells();
}
public class WhiteWizard : AbsWizard
{
// organizes all the spells available to the wizard...
public sealed class Spells
{
// NOTE: Spells may be better off as a specific class, rather than as strings.
// Then you could decorate them with a lot of other information (cost, category, etc).
public const string Abracadabra = "Abracadabra";
public const string AlaPeanutButterSandwiches = "APBS";
}
}
public static void CastMagic()
{
Type[] types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes();
List<Type> wizardTypes = new List<string>();
List<string> avalibleSpells = new List<string>();
Type selectedWizardType;
string selectedSpell;
foreach (Type t in types)
{
if (typeof(AbsWizard).IsAssignableFrom(t))
{
// find a nested class named Spells and search it for public spell definitions
// better yet, use an attribute to decorate which class is the spell lexicon
var spellLexicon = Type.FromName( t.FullName + "+" + "Spells" );
foreach( var spellField in spellLexicon.GetFields() )
// whatever you do with the spells...
}
}
}
There are many ways to improve the above code.
First, you can define your own custom attribute that you can tag on the nested classes of each wizard to identify the spell lexicon.
Second, using strings to define the available spells may end up being a bit limiting. You may find it easier to define a global static list of all available spells (as some kind of class, let's call it Spell). You could then define the available spells of the wizard based off this list, rather than strings.
Third, consider creating an external configuration for this thing rather than embedded, nested classes. It's more flexible and possibly easier to maintain. However, it can be nice to write code like:
WhiteWizard.Spells.Abracadabra.Cast();
Finally, consider creating a static dictionary for each Wizard-derivative that manages the list of available spells so that you can avoid performing reflection (which is expensive) more than once.
Since spells are tied to the type of the wizard, I'd do this through attributes:
[AttributeUsage(AttributeTargets.Class)]
public class SpellsAttribute : Attribute
{
private string[] spells;
public WizardAttribute(params string[] spells)
{
this.spells = spells;
}
public IEnumerable<string> Spells
{
get { return this.spells ?? Enumerable.Empty<string>(); }
}
}
Then you declare a wizard type like this:
[Spells("booblah","zoombar")]
public class WhiteWizard : AbsWizard
{
public override Magic GetMagic(string magicWord) { ... }
}
Then the class that loads wizard types from the assembly can check each wizard class has this attribute and if so makes the type available (or throws an exception).
Does this do what you need? Add each type of wizard to the factory as needed. Wizards will never be instantiated outside of your library, only inside it. For someone outside your library to get a wizard, they make a call to the factory to get those wizards that support a given spell. The factory sets itself up. Just register each new wizard with the factory.
public class Magic
{
}
public abstract class AbsWizard
{
public abstract Magic GetMagic(String magicword);
public abstract string[] GetAvalibleSpells();
internal AbsWizard()
{
}
}
public class WhiteWizard : AbsWizard
{
public override Magic GetMagic(string magicword)
{
return new Magic();
}
public override string[] GetAvalibleSpells()
{
string[] spells = { "booblah", "zoombar" };
return spells;
}
}
public static class WizardFactory
{
private static Dictionary<string, List<AbsWizard>> _spellsList = new Dictionary<string, List<AbsWizard>>();
/// <summary>
/// Take the wizard and add his spells to the global spell pool. Then register him with that spell.
/// </summary>
/// <param name="wizard"></param>
private static void RegisterWizard(AbsWizard wizard)
{
foreach (string s in wizard.GetAvalibleSpells())
{
List<AbsWizard> lst = null;
if (!_spellsList.TryGetValue(s, out lst))
{
_spellsList.Add(s, lst = new List<AbsWizard>());
}
lst.Add(wizard);
}
}
public string[] GetGlobalSpellList()
{
List<string> retval = new List<string>();
foreach (string s in _spellsList.Keys)
{
retval.Add(s);
}
return retval.ToArray<string>();
}
public List<AbsWizard> GetWizardsWithSpell(string spell)
{
List<AbsWizard> retval = null;
_spellsList.TryGetValue(spell, out retval);
return retval;
}
static WizardFactory()
{
RegisterWizard(new WhiteWizard());
}
}
Use a factory class to instantiate your wizards. The factory has a
public static string[] GetSpellsForWizardType(Type wizardType)
method that allows you to determine which spells a wizard can cast. The factory also calls this same method to construct a new wizard instance and set its spell set.

Categories

Resources