Pass around an "AppendOnlyStringBuilder" - c#

I have a serialization task where different parts and pieces of my object model know how to emit their own string segments, but I'd like the option to emit them using .Append against a common StringBuilder object. On the theory that we should not pass around our private objects for others to use indiscriminately, here's a class that wraps a StringBuilder to make it "append-only" for use in my scenario.
public sealed class AppendOnlyStringBuilder {
private readonly StringBuilder _stringBuilder;
public AppendOnlyStringBuilder(StringBuilder stringBuilder)
{
_stringBuilder = stringBuilder;
}
public AppendOnlyStringBuilder Append<T>(T value)
{
_stringBuilder.Append(value);
return this;
}
}
If my code inside of the different chunks of my model right now all look similar to this:
// Chunk1 class
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb
.Append(_prop1.Value)
.Append(_prop2.Value)
.Append(_prop3.Value);
return sb.ToString();
}
And these ToString methods are called from the main routine's serialization method like so:
// MainObject class
Chunk1 _chunk1;
Chunk2 _chunk2;
Chunk3 _chunk3;
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb
.Append(_chunk1.ToString()) // ToString may be unnecessary here
.Append(_chunk2.ToString())
.Append(_chunk3.ToString());
return sb.ToString();
}
How can I elegantly switch to passing around a single AppendOnlyStringBuilder for use in all these chunk classes instead of each one internally creating a new StringBuilder and doing ToString?
I'd like it to be used something like this:
// MainObject class
public override string ToString() {
StringBuilder sb = new StringBuilder();
AppendOnlyStringBuilder aosb = new AppendOnlyStringBuilder(sb);
aosb
.Append(_chunk1)
.Append(_chunk2)
.Append(_chunk3);
return sb.ToString();
}
An extension method is a natural way to get this syntax, but I'm running into problems due to the extension method needing to be static and thus not able to access private parts of the Chunk classes. I'd like to keep the same ToString in the chunk classes so they can still do their normal "serialize just me" thing, but I'd also like for them to be able to optionally append to my common AppendOnlyStringBuilder.
I guess I could do this:
_chunk1.AppendTo(aosb);
_chunk2.AppendTo(aosb);
_chunk3.AppendTo(aosb);
But something about that bugs me--I'd like to use a fluent interface that begins with the AppendOnlyStringBuilder object as in my example previously.

Ok, here goes:
using System.IO;
abstract class BaseClass
{
protected abstract void WriteToTextWriter(TextWriter textWriter);
public void SerializeTo(TextWriter textWriter)
{
WriteToTextWriter(textWriter);
}
public sealed override string ToString()
{
var writer = new StringWriter();
SerializeTo(writer);
return writer.ToString();
}
}
abstract class ChunkBase : BaseClass
{
private readonly string _index;
protected ChunkBase(string index)
{
_index = index;
}
protected sealed override void WriteToTextWriter(TextWriter textWriter)
{
textWriter.Write("Chunk");
textWriter.Write(_index);
}
}
class Chunk1 : ChunkBase { public Chunk1() : base("1") { } }
class Chunk2 : ChunkBase { public Chunk2() : base("2") { } }
class Chunk3 : ChunkBase { public Chunk3() : base("3") { } }
class ClassWithChunks : BaseClass
{
private readonly Chunk1 _chunk1 = new Chunk1();
private readonly Chunk2 _chunk2 = new Chunk2();
private readonly Chunk3 _chunk3 = new Chunk3();
protected override void WriteToTextWriter(TextWriter textWriter)
{
_chunk1.SerializeTo(textWriter);
_chunk2.SerializeTo(textWriter);
_chunk3.SerializeTo(textWriter);
}
}
Now, if you want chaining, you could do this:
class Chainable
{
private readonly TextWriter _textWriter;
public Chainable(TextWriter textWriter)
{
_textWriter = textWriter;
}
public Chainable Write(BaseClass obj)
{
obj.SerializeTo(_textWriter);
return this;
}
}
Then, your WriteToTextWriter could be, for example, this:
public override void WriteToTextWriter(TextWriter textWriter)
{
new Chainable(textWriter)
.Write(_chunk1)
.Write(_chunk2)
.Write(_chunk3);
}
I'm not sure it's worth it: the code is certainly cleaner, but it will be harder for someone (including your future self) to decipher, because of the additional layer of complexity.
Edit: Making the abstract method protected seems to add little here, but in production code, the extra layer could well be helpful. You'll want to add some switches, too, to handle formatting and the like.

Seems like the ideal candidate for the adapter pattern.
(untested code)
public interface IAppendOnly
{
void Append(string content);
}
public class AppendOnlyStringBuilder : IAppendOnly
{
private StringBuilder _stringBuilder = new StringBuilder()
public void Append(string content)
{
_stringBuilder.Append(content);
}
public override string ToString()
{
return _stringBuilder.ToString();
}
}
public class Chunk
{
public void AppendTo(IAppendOnly appendOnly)
{
appendOnly.Append("My Content");
}
}
Then each Chunk works without the knowledge of how the interface was instantiated:
_chunk1.AppendTo(aosb);
_chunk2.AppendTo(aosb);
_chunk3.AppendTo(aosb);
But something about that bugs me--I'd like to use a fluent interface that begins with the AppendOnlyStringBuilder object as in my example previously.
So with this requirement (minus the unnecessary AppendOnlyStringBuilder class) you'd then switch the interface direction.
public interface IGetString
{
string GetString();
}
public Chunk : IGetString
{
public string GetString()
{
return "MyContent";
}
}
public static class StringBuilderExtensions
{
public static StringBuilder AppendFrom(this StringBuilder instance
, IGetString getString)
{
instance.Append(getString.GetString())
return instance;
}
}
Then it's Fluent:
var sb = new StringBuilder;
var a = new Chunk();
var b = new Chunk();
sb.AppendFrom(a).AppendFrom(b);

If you want only one instatiated object of a type you could use the singleton pattern (Google will give you many exampels)
If you have a global object (something like a "myApplication"-class) you could offer this there.
Other way is a static class offering this singleton instance "from everywhere".
Your code would append directly to this one instance...
Hope this helps

Related

Is BaseClass is allowed in strategy pattern

I have created a solution to read/process various kinds of files, e.g. XML, JSON, txt.
public interface IFileProcessor
{
TOutput Process<TInput, TOutput>(TInput input);
}
public abstract class FileProcessorBase
{
protected readonly FileInfo fileInfo;
protected FileProcessorBase(FileInfo fileInfo)
{
this.fileInfo = fileInfo;
}
protected abstract TOutput Load<TOutput>();
}
And the concrete class as follows.
public class JsonFileProcessor : FileProcessorBase, IFileProcessor
{
public JsonFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
//Call Load Method
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
protected override TOutput Load<TOutput>()
{
string res = "JSON Load method";
return (TOutput)Convert.ChangeType(res, typeof(TOutput), CultureInfo.InvariantCulture);
}
}
Concrete class for XML
public class XMLFileProcessor : FileProcessorBase, IFileProcessor
{
public XMLFileProcessor(FileInfo fileInfo) : base(fileInfo)
{
}
public TOutput Process<TInput, TOutput>(TInput from)
{
string res = Load<string>();
return (TOutput)Convert.ChangeType(res, typeof(TOutput));
}
protected override TOutput Load<TOutput>()
{
string xml = "XML";
return (TOutput)Convert.ChangeType(xml, typeof(TOutput));
}
}
and now this is factory class
public class FileProcessorFactory
{
static readonly Dictionary<string, IFileProcessor> fileProcessor;
static FileProcessorFactory()
{
fileProcessor = new Dictionary<string, IFileProcessor>();
fileProcessor.Add("XML", new XMLFileProcessor(new FileInfo(""));
fileProcessor.Add("JSON", new JsonFileProcessor(new FileInfo(""));
}
public static IFileProcessor GetFileProcessor(string key)
{
return fileProcessor[key];
}
}
Below is FileProcessorService class
public class FileProcessorService
{
IFileProcessor fileProcessor;
public FileProcessorService(IFileProcessor fileProcessor)
{
this.fileProcessor = fileProcessor;
}
public TOutput Process<TInput, TOutput>(TInput from)
{
return fileProcessor.Process<TInput, TOutput>(from);
}
}
Now Finally, I'm calling through this way.
IFileProcessor fileProcessor = FileProcessorFactory.GetFileProcessor("XML");
FileProcessorService fileProcessorService = new FileProcessorService(fileProcessor);
var XMLResult = fileProcessorService.Process<string, string>("");
Can I use base class in strategy pattern, If not what would be proposed solution.
This may help answer your specific question with regards whether their are any hard rules to say that the strategy pattern should not inherit any base implementation.
Can i use inheritance instead of implement an interface in strategy pattern?
In terms of your code have you considered passing an interface that has a method to return the stream of data, as opposed to using concrete FileInfo - as you could then remove base class entirely.

Breaking SOLID Principles in multiple implementation of an Interface

I am facing a problem with dependency inversion in a factory method and it is also breaking Open Closed principle. My code looks like below codes
public interface IWriter
{
void WriteToStorage(string data);
}
public class FileWriter : IWriter
{
public void WriteToStorage(string data)
{
//write to file
}
}
public class DBWriter : IWriter
{
public void WriteToStorage(string data)
{
//write to DB
}
}
Now I an using a factory class to solve the object creation. It look like below code
public interface IFactory
{
IWriter GetType(string outputType);
}
public class Factory : IFactory
{
public IWriter GetType(string outputType)
{
IWriter writer = null;
if (outputType.Equels("db"))
{
writer = new FileWriter();
}
else if (outputType.Equels("db"))
{
writer = new DBWriter();
}
}
}
Now the problem is the Factory class is breaking Open closed principle so it also breakes Dependency Inversion Principle
And then
public interface ISaveDataFlow
{
void SaveData(string data, string outputType);
}
public class SaveDataFlow : ISaveDataFlow
{
private IFactory _writerFactory = null;
public SaveDataFlow(IFactory writerFactory)
{
_writerFactory = writerFactory;
}
public void SaveData(string data, string outputType)
{
IWriter writer = _writerFactory.GetType(outputType);
writer.WriteToStorage(data);
}
}
As the above factory class is breaking the dependency inversion I remove the Factory class and change the SaveDataFlow class like below
public class SaveDataFlow : ISaveDataFlow
{
private IWriter _dbWriter = null;
private IWriter _fileWriter = null;
public SaveDataFlow([Dependency("DB")]IWriter dbWriter,
[Dependency("FILE")]IWriter fileWriter)
{
_dbWriter = dbWriter;
_fileWriter = fileWriter;
}
public void SaveData(string data, string outputType)
{
if (outputType.Equals("DB"))
{
_dbWriter.WriteToStorage(data);
}
else if (outputType.Equals("FILE"))
{
_fileWriter.WriteToStorage(data);
}
}
}
And resolved those dependencies using Unity Framework
container.RegisterType<IWriter, DBWriter>("DB");
container.RegisterType<IWriter, FileWriter>("FILE");
Yet eventually I am ending up breaking Open Closed Principle.
I need a better design/solution to solve such a problem yet I must follow SOLID Principles.
I would simply turn it into a strategy pattern:
namespace UnityMutliTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IWriter, FileWriter>("file");
container.RegisterType<IWriter, DbWriter>("db");
container.RegisterType<IWriterSelector, WriterSelector>();
var writerSelector = container.Resolve<IWriterSelector>();
var writer = writerSelector.SelectWriter("FILE");
writer.Write("Write me data");
Console.WriteLine("Success");
Console.ReadKey();
}
}
interface IWriterSelector
{
IWriter SelectWriter(string output);
}
class WriterSelector : IWriterSelector
{
private readonly IEnumerable<IWriter> writers;
public WriterSelector(IWriter[] writers)
{
this.writers = writers;
}
public IWriter SelectWriter(string output)
{
var writer = this.writers.FirstOrDefault(x => x.CanWrite(output));
if (writer == null)
{
throw new NotImplementedException($"Couldn't find a writer for {output}");
}
return writer;
}
}
interface IWriter
{
bool CanWrite(string output);
void Write(string data);
}
class FileWriter : IWriter
{
public bool CanWrite(string output)
{
return output == "FILE";
}
public void Write(string data)
{
}
}
class DbWriter : IWriter
{
public bool CanWrite(string output)
{
return output == "DB";
}
public void Write(string data)
{
}
}
}
You can have as many IWriters as you want, just register them:
container.RegisterType<IWriter, LogWriter>("log");
You can even implement decorators over the writers if you want as well.
You use the (badly named) IWriterSelector as the implementation on how to select your writer, this should be concerned with only getting a writer! The throw exception here is really useful, it will fail fast if there is no implementation that suits your needs!!
If you ever have Open Closed problems, either use Strategy or Template patterns to overcome.
I use this pattern all the time, to great effect.
I've created a little extension method to prevent you having to name your instances:
static class UnityExtensions
{
public static void RegisterMultipleType<TInterface, TConcrete>(this IUnityContainer container)
{
var typeToBind = typeof(TConcrete);
container.RegisterType(typeof(TInterface), typeToBind, typeToBind.Name);
}
}
container.RegisterMultipleType<IWriter, FileWriter>();
Solution 1
Choose before instantiation and use scopes
using(var scope = new Scope(unity))
{
scope.register<IWriter, ConcreteWriter>();
var flow = scope.Resolve<ISaveDataFlow>();
}
Solution 2
Inject your strategy at runtime.
ISaveDataFlow flow = ....
IWriter writer = GetWriterBasedOnSomeCondition();
flow.SaveData(data, writer);
I suspect that solution 2 is closer to what you are trying to achieve. Remember, you don't need to pass around a string to describe the strategy you want to use.
You can instead pass around the actual strategy you want to use, in this case, the actual IWriter, you want to use.
Then what you can do instead is have metadata on each IWriter to help the user choose which IWriter to use.
For example
public interface IWriter
{
void WriteData(data);
string Name {get;}
}
void GetWriterBasedOnSomeCondition()
{
Dictionary<string, IWriter> writers = ...ToDictionary(x => x.Name);
var choice = Console.ReadLine();
return writers[choice];
}
I tend to use one of these approaches.
1. Break into different interfaces
public interface IWriter
{
void WriteToStorage(string data);
}
public interface IFileWriter : IWriter
{
}
public interface IDBWriter: IWriter
{
}
public class FileWriter : IFileWriter
{
public void WriteToStorage(string data)
{
//write to file
}
}
public class DBWriter : IDBWriter
{
public void WriteToStorage(string data)
{
//write to DB
}
}
Pros: You can inject the correct implementation based on the interface, which doesn't break the OCP.
Cons: You have empty interfaces.
2. Use an enum to separate them (strategy pattern)
public interface IWriter
{
void WriteToStorage(string data);
StorageType WritesTo { get; }
}
public enum StorageType
{
Db = 1,
File = 2
}
public class Factory : IFactory
{
public IEnumerable<IWriter> _writers;
public Factory(IWriter[] writers)
{
_writers = writers;
}
public IWriter GetType(StorageType outputType)
{
IWriter writer = _writers.FirstOrDefault(x => x.WritesTo == outputType);
return writer;
}
}
Pros: You can inject them both and then use the one you want by using the enum.
Cons: I guess it kinda breaks the OCP-principle the same way as in your first example.
More about the strategy pattern in this excellent answer from Mark Seemann.
3. Build a factory that creates items based on a func.
In your registration:
container.RegisterType<IWriter, DBWriter>("DB");
container.RegisterType<IWriter, FileWriter>("FILE");
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(
new Func<string, IWriter>(
writesTo => container.Resolve<IWriter>(writesTo));
And your factory
public class Factory : IFactory
{
private readonly Func<string, IWriter> _createFunc;
public Factory(Func<string, IWriter> createFunc)
{
_createFunc = createFunc;
}
public IWriter CreateScope(string writesTo)
{
return _createFunc(writesTo);
}
}
Pros: Moves the entire dependency to the registration.
Cons: A wrapper for a service-locator pattern. Can be a bit hard to read.
None of the examples above is perfect, as each of them has their pros and cons.
Similiar question here:
Inject require object depends on condition in constructor injection
In .NET Core (it's not clear from the question what framework is being used), you can use the built-in DI to achieve the strategy pattern quite easily with very little code.
In Startup.ConfigureServices:
services
.AddScoped<IWriter, FileWriter>()
.AddScoped<IWriter, DBWriter>()
.AddScoped<ISaveDataFlow, SaveDataFlow>();
Add an method to IWriter for the strategy algorithm:
public interface IWriter
{
bool CanWrite(string outputType);
void WriteToStorage(string data);
}
public class FileWriter : IWriter
{
bool CanWrite(string outputType) => outputType == "FILE";
public void WriteToStorage(string data) {}
}
public class DBWriter : IWriter
{
bool CanWrite(string outputType) => outputType == "DB";
public void WriteToStorage(string data) {}
}
Then change the constructor of SaveDataFlow to use a collection type, and change SaveData to call the algorithm method of all resolved IWriter types.
public class SaveDataFlow : ISaveDataFlow
{
private readonly IWriter _writers;
public SaveDataFlow(IEnumerable<IWriter> writers)
{
_writers= writers;
}
public void SaveData(string data, string outputType)
{
_writers.Single(w => w.CanWrite(outputType)).WriteToStorage(data);
}
}
This now complies with the Open/Closed Principle as the concrete selection is only within the concrete classes themselves.

Using methods on Generics

I have a ton of methods like this:
public UIPCompanyButton AddCompanyButton (string name, Company company, UIEventListener.VoidDelegate methodToCall, GameObject contents)
{
return UIPCompanyButton.Create (name, company, methodToCall, contents);
}
that I'd like to replace with a single method like this:
public T AddButton<T,K>(string name, K item, UIEventListener.VoidDelegate methodToCall, GameObject contents) where T:UIPMenuButton
{
return T.Create(name, item, methodToCall, contents);
}
which obviously doesn't work at the T.Create part. Is there a certain syntax I need to do this?
I'm also open to a different method with the same result: a single method that takes in a derived menuButton and creates the right one with the right class of "item".
No, you can't call static methods on generic types - not without reflection. Aside from anything else, there's no way of constraining a generic type to have specific static members. The closest to that is the parameterless constructor constraint.
What you want is a factory to create your objects. Here is a small working example. It might not be the best way to implement a factory pattern, but it should get you going.
For a more in depth example and explanation, see this page.
public class Button {
public string Whatever { get; set; }
public Button() {
Whatever = "Hello, world!";
}
}
public interface IAddButton {
Button CreateButton();
}
public class ClassToMakeButtonFor1 {
public static void RegisterMe() {
ButtonFactory.Register(typeof(ClassToMakeButtonFor1), new ButtonFactory1());
}
}
public class ButtonFactory1 : IAddButton {
public Button CreateButton() {
return new Button();
}
}
public class ClassToMakeButtonFor2 {
public static void RegisterMe() {
ButtonFactory.Register(typeof(ClassToMakeButtonFor2), new ButtonFactory2());
}
}
public class ButtonFactory2 : IAddButton {
public Button CreateButton() {
var b = new Button { Whatever = "Goodbye!" };
return b;
}
}
public static class ButtonFactory {
private static Dictionary<Type, IAddButton> FactoryMap = new Dictionary<Type, IAddButton>();
public static void Register(Type type, IAddButton factoryClass) {
FactoryMap[type] = factoryClass;
}
public static Button MakeMeAButton<T>() where T : class {
return FactoryMap[typeof(T)].CreateButton();
}
}
internal class Program {
private static void Main(string[] args) {
ClassToMakeButtonFor1.RegisterMe();
ClassToMakeButtonFor2.RegisterMe();
Button b = ButtonFactory.MakeMeAButton<ClassToMakeButtonFor1>();
Console.WriteLine(b.Whatever);
b = ButtonFactory.MakeMeAButton<ClassToMakeButtonFor2>();
Console.WriteLine(b.Whatever);
Console.ReadLine();
}
}
What you could consider is to have some interface (e.g. ICreator) that defines a Create method you want to call.
Then you would constrain your type parameter to types that implement the interface ( where T : ICreator).
Then you would call the method on an instance, not a static method. So in your case maybe you could call item.Create(...).
Makes any sense for your case?
It sounds like you might be able to make your Button class generic. Depending on how much logic lives in each of these derived classes, this may not work for you.
class Button<T>
{
public T Item { get; private set; }
public Button(string name, T item, ...)
{
// Constructor code
}
}
// Helper class for creation
static class Button
{
public static Button<T> Create<T>(string name, T item, ...)
{
return new Button<T>(name, item, ...);
}
}
Then, to use this:
Button<Company> button = Button.Create("Name", company, ...);

How to create an abstract method with a parameter of type of implementing class

I have got a abstract class with an abstract method taking a parameter of the type of the implementing class. I can achieve this by generics like this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass>)
{
// implementation
}
}
Unfortunately I need in one of the implementing classes a list of Clazz<T> elements.
So how can I achieve this?
Of cause List<Clazz<T>> does not work.
List<Clazz<MyClass>> is too restrictive.
Removing the generics and the abstract method does work (my current solution), but this way I could forget to implement the CopyFrom() method in one of the implementing classes.
Edit: Here comes a more detailed example:
I've got an abstract class:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
// ...
}
And a derived class:
class MyDerivedClass : Clazz<MyDerivedClass >
{
public string Text;
private readonly List<MySubClass> _list = new List<MySubClass>();
public override void CopyFrom(MyDerivedClass source)
{
Text = source.Text;
}
private List<Clazz> GetAllItems()
{
List<Clazz> list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
}
private class MySubClass : Clazz<MySubClass>
{
public int Number;
public override void CopyFrom(MySubClass source)
{
Number = source.Number;
}
}
}
There are several other deriving classes, the GetAllItems() Method is only needed in MyDerivedClass.
would this suffice? without more details it is hard to tell.
interface ICopyMaker
{
void CopyFrom(ICopyMaker source);
}
abstract class Clazz<T> : ICopyMaker
{
public abstract void CopyFrom(Clazz<T> source);
void ICopyMaker.CopyFrom(ICopyMaker source)
{
var src = source as Clazz<T>;
if (src == null) return; // know how to copy only from the instances of the same type
CopyFrom(src);
}
}
class MyClass : Clazz<MyClass>
{
private List<ICopyMaker> _list = new List<ICopyMaker>();
public override void CopyFrom(Clazz<MyClass> c)
{
//implementation
}
}
You can make the respective method generic, too, and introduce a constraint that takes T into account. If I understand well what you want to achieve, you can do this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
public abstract void ProcessList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<T>;
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass> source)
{
// implementation
}
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
}
You can also easily include list processing in a descendant, like this:
class MyOtherClass : Clazz<MyOtherClass>
{
public override void CopyFrom(Clazz<MyOtherClass> source)
{
// implementation
}
// this list processing is inherited
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
// this list processing is specific to this descendant only
public void ProcessMyClassList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<TMyClass>
{
// implementation
}
}
Then use can declare a descendant of MyClass, which in turn is a Clazz<T>, T being MyClass:
class MyDescendant : MyClass
{
}
The following works:
List<MyDescendant> list = new List<MyDescendant>();
new MyClass().ProcessList(list);
In case of MyOtherClass, the situation is a little bit different. ProcessMyClassList accepts a list of Clazz<T> or its descendants; however, not those related to MyOtherClass but to the good-ol' MyClass. This code works:
List<MyDescendant> list = new List<MyDescendant>();
new MyOtherClass().ProcessMyClassList(list); // this works
But the following won't compile:
List<MyOtherClass> list = new List<MyOtherClass>();
new MyOtherClass().ProcessList(list); // this works
new MyOtherClass().ProcessMyClassList(list); // this doesn't
Thank's everyone for your answers, but I think I have figured out a solution I can live with:
I will remove the generics and add a typecheck, like in the solution from anikiforov:
Abstract class:
abstract class Clazz
{
public abstract void CopyFrom(Clazz source);
}
And the derived class:
class MyDerivedClass : Clazz
{
public string Text;
private List<MyNestedClass> _list;
public override void CopyFrom(Clazz source)
{
var src = source as MyDerivedClass;
if (src == null) return;
Text = src.Text;
}
public List<Clazz> GetAllItems()
{
var list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
return list;
}
class MyNestedClass : Clazz
{
public int Number;
public override void CopyFrom(Clazz source)
{
var src = source as MyNestedClass;
if (src == null) return;
Number = src.Number;
}
}
}

Invoke a Method anonymous class

I am quite new to the C# world and I apologize if the Question title not exactly match the content. But now to my Problem:
I have the following construct:
public interface IClass<TEnum>
{
Dictionary<TEnum, ISecondClass> dictionary { get; }
}
public abstract class ClassBase<TEnum> : IClass<TEnum>
{
public abstract Dictionary<TEnum, ISecondClass> dictionary { get; protected set; }
}
public class ConcreteClass : ClassBase<ConcreteClass.Concrete>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Other : ulong
{
}
}
My goal is to instantiate all existing concrete classes based on it's enums, store all instances in a dictionary and later invoke some methods on each object.
I am not sure if this is even possible?
I am glad for any hint on this!
If I understand what you're trying to do, it sounds like a version of the Multiton Pattern. You may find it useful to research that.
From Wikipedia's example Multiton code:
class FooMultiton
{
private static readonly Dictionary<object, FooMultiton> _instances = new Dictionary<object, FooMultiton>();
private FooMultiton() {}
public static FooMultiton GetInstance(object key)
{
lock (_instances)
{
FooMultiton instance;
if (!_instances.TryGetValue(key, out instance))
{
instance = new FooMultiton();
_instances.Add(key, instance);
}
}
return instance;
}
}
This isn't directly pasteable into your class, but since you're looking for hints, I think it should point you in the right direction.
One word of caution about the above code: The method GetInstance will alter the dictionary if key isn't found. Personally, I associate the "Get" prefix with read-only methods. I'd either rename GetInstance or split it into two methods.
I'm not really sure what you mean by "instantiate all existing concrete classes based on it's enums", though. Can you clarify that?
Use Activator.CreateInstance() to create concrete classes' objects and store them into dictionary.
Pass your string classname from Enum and create dynamic class objects. Store them into Dictionary<Enum, ISecondClass>
myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");
or
var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
While retrieving, based on your enum key, you know what type of instance value represents.
I don't understand a goal of the sample code, but you can write some thing like this:
public interface IClass
{
void MethodToDynamicInvoke();
}
public abstract class ClassBase<T>
: IClass
{
private Dictionary<Type, List<IClass>> instances = new Dictionary<Type, List<IClass>>();
public ClassBase()
{
List<IClass> list;
if (!instances.TryGetValue(typeof(T), out list))
{
list = new List<IClass>();
instances.Add(typeof(T), list);
}
list.Add(this);
}
public abstract void MethodToDynamicInvoke();
public void InvokeMetodOnClassesWithSameEnum()
{
List<IClass> list;
if (instances.TryGetValue(EnumType, out list))
{
foreach (var instance in list)
{
instance.MethodToDynamicInvoke();
}
}
}
}
public class ConcreteClass
: ClassBase<ConcreteClass.Concrete>
{
public ConcreteClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public OtherClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Other : ulong
{
}
}

Categories

Resources