My main class Computer interacts with a number of external systems and currently has the logic for getting/updating their info crammed into it.
I want to move the logic for each system to it's own separate class and i've been able to part of the way there but i'm having trouble calling a method on them.
I've only just recently started playing around with generics so this is probably badly written code, apologies for your eyes in advance.
These are my System classes
public class System
{
public string Name { get;set; }
}
public class System<T> : System
{
public virtual T GetData() => default(T);
public virtual void UpdateData() {}
}
public interface ISystem<T>
{
T GetData();
void UpdateData();
}
These are the systems i've created using the System classes:
public class ComplexSystem : ISystem<RegistryKey>
{
public string GetData() => MethodThatGetsRegistryData();
public bool UpdateData() => MethodThatUpdatesRegistry();
}
public class IntSystem : ISystem<int>
{
private int value = 9;
public int GetData() => this.value;
public void UpdateData()
{
this.value = 3;
}
}
public class StringSystem : ISystem<string>
{
private string value = "hello";
public string GetData() => this.value;
public void UpdateData()
{
this.value = "updated";
}
}
and this is how i'm trying to use the whole thing:
public class Computer
{
public List<System> AssociatedSystems = new List<System>();
public Computer()
{
this.AssociatedSystems.Add(new System<ComplexSystem> {Name="ComplexSystem"});
this.AssociatedSystems.Add(new System<IntSystem> {Name="IntSystem"});
this.AssociatedSystems.Add(new System<StringSystem> {Name="StringSystem"});
}
public void UpdateDataWhenComputerIsChanged()
{
// is it possible to loop through them and call UpdateData on each one without know what generic they are?
foreach (var associatedSystem in this.AssociatedSystems)
{
// something like...
associatedSystem.UpdateData();
}
}
}
Which results in
System does not contain a definition for UpdateData() and no extension method could be found
I'm not married to the code above so if there's a better way of doing it i'm all for learning. I'm essentially looking for a way to have a list of classes that contain data logic (like GetData() and UpdateData()) so i don't have to put that logic into my main class (Computer)
So function UpdateData does not exist in System and that is why you cant call it. I would suggest introducing an ISystem interface and put Name (if you need it) and UpdateData in that and let the generic ISystem<T> interface inherit from that.
public interface ISystem
{
string Name {get;set;}
void UpdateData();
}
public interface ISystem<T> : ISystem
{
T GetData();
}
public class Computer
{
public List<ISystem> AssociatedSystems = new List<ISystem>();
.....
foreach (var associatedSystem in this.AssociatedSystems)
{
associatedSystem.UpdateData();
}
}
Yes there are multiple ways to do this. The ones that I can think of are:
Type checking each System in the loop
Adding a Type property to system
Adding a UpdateData(object) or UpdateData(SomeHighLevelType)
If you need more help please specify the nature of your systems. Are they limited to some specific types or you want is extendable for ever and how much speed critical is your project and I can elaborate more
Related
I though I would easily find an answer to this question but I couldn't find yet.
Let's say I have the following classes :
public class Universe
{
public list<Human> Humans { get; set; }
public list<Animal> Animals { get; set; }
public God AlphaOmega { get; set; }
public void UniverseAction()
{
//dosmthg
}
public Animal FindAnAnimal()
{
//find an animal
}
}
public class Animal
{
//many Animal things
public void AnimalyStuff()
{
//DoSmthg
}
}
public class God
{
public bool CantTouchThis = true;
}
public class Human
{
//many Human things
public void CallingUniverseAction()
{
//How to?
}
public void CallingAnimalyStuff()
{
}
}
Note that those names are purely given as examples, I could have used A, B, C & D.
So I want that all humans be able to call UniverseAction() so from a specific Human I can use it.
I also want that humans be able to call AnimalyStuff() so a specific Human would need to access the FindAnAnimal in Universe to retrieve a specific Animal and do the AnimalyStuff()
For a while when dealing with this kind of requirement I used to pass Universe in the constructor of Human. Though I don't want that Human can expose all method / parameters of Universe. For instance, Human should not interract with AlphaOmega
What would be the most appropriate way to do it?
Is it through an action delegate that I'll pass in the constructor? If so how, I never used action delegates. Also will I not end up with passing many delegates if I want Human to access many methods?
You have a couple options available to you if you want to limit the available information to Human.
If you are okay with only hiding the information, where it is still there, but not accessible unless you explicitly un-hide it consider using a Interface to limit the available members.
If you are okay with the Universe being passed around, but certain members being inaccessible to Human, consider using the protected modifier to limit access to members that inherit from the Universe class.
If you are okay with passing things in the constructor(like you recommended) you could pass any number of methods(delegates) to the human class so they can get the information any time they need, but it involves more complex implementation(I already did most of the work for you below)
If you're not sure what you want to do, and this doesn't need(for some specific business requirement) to work in the way you have described - Consider researching general Object Oriented Programing design patterns. There's a ton of resources online that can teach you OOP. The main topic I would recommend is the SOLID principles which will teach you a lot and be really useful. Thanks #flydog57 for mentioning this, as this would be more useful in the long run.
Interfaces
To visually hide/abstract the information unless explicitly accessed(casted) you can implement an IUniverse interface that defines only the members that you want publicly accessible.
// these would be the only accessible members
public interface IUniverse
{
Animal FindAnAnimal();
void UniverseAction();
}
public class Universe : IUniverse { ... }
public class Human
{
private readonly IUniverse universe;
public Human(IUniverse universe)
{
this.universe = universe;
}
}
Using interfaces to abstract which information should be available where can be really powerful! However, this does not prevent Human from casting the IUniverse to a Universe object explicitly and access it's other public members.
Protected Modifier
You can use the protected modifier (and a couple other ones) to completely remove access to information to other classes that don't meet certain requirements. For example the protected modifier would prohibit access to any protected members from any class that does not inherit from Universe. Make sure to checkout Access Modifiers for more information about the other options available to you.
public class Universe
{
protected List<Human> Humans { get; set; } = new();
protected List<Animal> Animals { get; set; } = new();
protected God AlphaOmega { get; set; }
public void UniverseAction()
{
//dosmthg
Console.WriteLine(nameof(UniverseAction));
}
public Animal FindAnAnimal()
{
//find an animal
Console.WriteLine(nameof(FindAnAnimal));
return Animals.FirstOrDefault();
}
}
public class Human
{
private readonly Universe universe;
public Human(Universe universe)
{
this.universe = universe;
}
//many Human things
public void CallingUniverseAction()
{
//How to?
universe.UniverseAction(); // works
UniverseAction.Humans.Clear(); // no access it's protected
}
public void CallingAnimalyStuff()
{
var animal = universe.FindAnAnimal(); // works
UniverseAction.Animals.Clear(); // no access it's protected
AlphaOmega.Kill(); // no access it's protected
}
}
Passing Delegates
You could for example pass delegates to the human to avoid passing around the Universe instance it self. Any method group is usually convertible to some form of Action or Func. Make sure to checkout Actions and Funcs for more information on both and how they can be passed around.
You can pass these around super simply for example:
public class Universe
{
public Human CreateHuman()
{
var newHuman = new Human(UniverseAction, FindAnAnimal);
Humans.Add(newHuman);
return newHuman;
}
}
public class Human
{
private readonly Action universeAction;
private readonly Func<Animal> animalyStuff;
public Human(Action universeAction, Func<Animal> animalyStuff)
{
this.universeAction= universeAction;
this.animalyStuff = animalyStuff;
}
//many Human things
public void CallingUniverseAction()
{
//How to?
universeAction?.Invoke();
}
public void CallingAnimalyStuff()
{
var animal = animalyStuff?.Invoke();
}
}
You could also implement a more robust, but more complex system if you need to pass a large amount of functions in the constructor like 20+. Passing a large number of things in a constructor is not a viable pattern, but it could work if you really wanted to, if you are required to do it to interop with legacy systems.
Here's a short snippet of what an implementation of that using reflection might look like.
public class Universe
{
protected List<Human> Humans { get; set; } = new();
protected List<Animal> Animals { get; set; } = new();
protected God AlphaOmega { get; set; }
public Human CreateHuman()
{
var newHuman = new Human(
(nameof(FindAnAnimal), (Func<Animal>)FindAnAnimal),
(nameof(UniverseAction), (Action)UniverseAction)
);
Humans.Add(newHuman);
return newHuman;
}
public void UniverseAction()
{
//dosmthg
}
public Animal FindAnAnimal()
{
//find an animal
}
}
public class Human
{
//many Human things
public void CallingUniverseAction()
{
Invoke(nameof(Universe.UniverseAction));
}
public void CallingAnimalyStuff()
{
var animal = Invoke(nameof(Universe.FindAnAnimal));
}
public Human(params (string Name, object Delegate)[] Methods)
{
foreach (var item in Methods)
{
InvokableReferences.Add(item.Name, item.Delegate);
}
}
private Dictionary<string, object> InvokableReferences = new();
public object Invoke(string DelegateName, params object[] Parameters)
{
if (InvokableReferences.ContainsKey(DelegateName))
{
object storedDelegate = InvokableReferences[DelegateName];
var delegateType = storedDelegate.GetType();
// check for the invoke method
var invokeMethod = delegateType.GetMethod(nameof(Invoke));
if (invokeMethod != null)
{
// check to see if it's an action or a func
var methodParams = invokeMethod.GetParameters();
if (methodParams is null)
{
// since there were no parameters then it is probably an Action or Func<T>
return invokeMethod.Invoke(storedDelegate, null);
}
// if it requires parameters it's probably a Action<T,..N> or Func<T...N,TResult>
// make sure we have enough parameters to invoke the method
if (methodParams.Length == Parameters.Length)
{
return invokeMethod.Invoke(storedDelegate, Parameters);
}
}
}
// if we failed to find the item return null;
return default;
}
}
In short, I'm hoping to achieve a kind of barebones structure in one place and implement/define in another. I want to better "see" the interconnectedness without all the functionality clouding it up mostly for design discussions, explanations, etc. I could do this with inheritance, but I really don't want to change all the names of everything just to achieve this. Is this a thing somehow?
// Simple File for seeing relationships between classes
public class AllMyObjectTypes // A class because it will be its own object with functionality below all this structural stuff
{
public class Thing1
{
public Thing2[] things2;
public Thing3[] things3;
}
public class Thing2[]
{
public int version;
public Thing1[] thing1Utilizers;
}
public class Thing3[]
{
public string Title;
}
}
// Complicated file for doing all the hard work for Thing1 with all the internal variables to make it happen.
public class Thing1 : Thing1 // Implement itself somehow?
{
// Stuff I want to use and define but not cloud the structure above
private int[] internalStuff;
private string moreInternalStuff;
public void UsefulFunctionButWantSeparated()
{
// Hundreds of lines of code clouding junk up
}
}
Interface & Class declarations
public interface IThing
{
IThing2[] Thing2s();
string DoSomething();
}
public class Thing : IThing
{
private readonly IThing2[] _thing2s = new IThing2[1] { new Thing2() };
public IThing2[] Thing2s() => _thing2s;
public string DoSomething()
{
return "MyText";
}
}
public interface IThing2
{
}
public class Thing2 : IThing2
{
}
Use
IThing thing;
thing = new Thing();
var thing2s = thing.Thing2s();
var txt = thing.DoSomething();
Partial Classes is exactly what I was looking for, but it did require that I don't nest within another class. Unless maybe I made that partial too...? But either way, this gets me closest to my goal
// Simple File for seeing relationships between classes
//public class AllMyObjectTypes // A class because it will be its own object with functionality below all this structural stuff
//{
public partial class Thing1
{
public Thing2[] things2;
public Thing3[] things3;
}
public partial class Thing2[]
{
public int version;
public Thing1[] thing1Utilizers;
}
public partial class Thing3[]
{
public string Title;
}
//}
// Complicated file for doing all the hard work for Thing1 with all the internal variables to make it happen.
public partial class Thing1 // More implementation
{
// Stuff I want to use and define but not cloud the structure above
private int[] internalStuff;
private string moreInternalStuff;
public void UsefulFunctionButWantSeparated()
{
// Hundreds of lines of code [no longer] clouding junk up
}
}
Lets say I have a class A which is going to be compiled into a dll to be used later. But I kind of know that later, some methods of class B which I am not aware of its type must be called in A class. The only clue is the name of the methods.
Lets say this is class A:
public class A
{
A(Object instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
Lets say this is class B, happen to be a WinForm:
public B : Form
{
public void ReceiveData(string data)
{
textBox.Append(data + Environment.NewLine);
}
}
Is such approach possible/recommended?
Yes, this is possible using the dynamic keyword (in C# 4.0 or higher). Check the MSDN documentation for more info.
However, this leads to incredibly loose programming and can cause runtime issues that are difficult to debug. You're much better off creating an interface that class B will implement.
public class A
{
A(IDataReceiver instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
public B : Form, IDataReceiver
{
public void ReceiveData(string data)
{
textBox.Append(data + Environment.NewLine);
}
}
public interface IDataReceiver
{
void ReceiveData(string data);
}
You should be using interface. You class B must implement "MyInterface" interface and "MyInterface" should have method which are are expecting A to call.
public class A
{
A(MyInerface instanceOfClassB)
{
//stuff...
}
public void SendProcessedString()
{
//some strings has been processd, I know that class B is going
//to have a public method like ReceiveData(string data){/*---*/}
instanceOfClassB.ReceiveData(data);
}
}
If it is not possible to implement interface at class B, you need to use reflection. See here (How to use reflection to call method by name) on how to call a method from a Type (so you will have to pass the type in constructor of A.
It sounds you need to use an interface.
A little information about interfaces can be found here.
Basically you want to create an interface and get it as a parameter for class A and implement it in class B:
interface IDataReceiver
{
void ReceiveData(string data);
}
then class B decleration will look like:
public B : Form, IDataReceiver
And class A` constructor:
A(IDataReceiver dataReceiver)
{
//stuff...
}
Another option here would be to use events. Have your raise an event instead of invoking the callback.
excuse my C#, I'm a little rusty
public class classA {
public event DataReceived(string data);
public void SendProcessedString() {
// you got var data from somewhere
DataReceived(data)
}
}
Then subscribe to that event from your classB
// classB setup code or initializer:
instanceA.DataReceived += dataReceivedHandler;
private void dataReceivedHandler(string data) {
// do something with the data.
}
Yet another method is to use a proper callback - only if a single subscriber is guaranteed. If you need multiple subscribers use an event.
public class classA {
public Action<string> DataReceivedCallback = null;
public void SendProcessedString() {
if (null != DataReceivedCallback) { DataReceivedCallback.Invoke(data); }
}
}
somewhere in classB
instanceA.DataReceivedCallback = new Action<string>(dataReceivedHandler);
private void dataReceivedHandler(string data) {
// do something with the data.
}
I have a class that works as a layer above the database layer for easy database access and it works very fine.
But now I would like all methods that read from the database being able to be accessed asynchronously without any risk of doing something dangerous. So I thought that if I implement an interface with only the "read" methods I could refer to that interface instead of the normal class when working from an async thread.
Is there any better (but hopefully similar) way to make this happen?
Here's an example of how far I've tried, but without success:
// My two interfaces.
// The UserCoreManager class is the layer that works with the database
// layer for the users table.
// but the IUserCoreManagerAsync only reference the async friendly methods.
public interface IUserCoreManagerAsync
{
User GetData();
}
public interface ICoreAsync
{
IUserCoreManagerAsync User { get; }
}
So far, so good. By refering to the User in the ICoreAsync interface I would
theoretically only be able to Get data and not Save any?
Here's what my actual classes implementing the interfaces looks like:
public class UserCoreManager : IUserCoreManagerAsync
{
public User GetData()
{
...
}
public User SetData()
{
...
}
}
public partial class Core : ICoreAsync
{
private UserCoreManager user;
public UserCoreManager User // <- This is the tricky part
{
get
{
return user;
}
protected set
{
user = (UserCoreManager)value;
}
}
}
As you can see, The UserCoreManager has a SetData() method, so when working with it not refering too the interface it will not be thread safe for me.
But as you also can see, I don't implement the interface property returning a IUserCoreManagerAsync, but I was sort of hoping that the UserCoreManager property would do the trick.
How would you do this? My goal is to achieve something like this when working with these classes:
public void DoSomeAsyncWork(ICoreAsync core)
{
var myData = core.User.GetData();
}
public void DoSomeWork(Core core)
{
core.User.SetData("some data");
}
In this way I have the actual same object, but depending on which methods I give it to and how i cast it, they can be forced to work with them thread safe or not.
Check this out
public interface IUserCoreMagagerWrite
{
public void SetData(User user);
}
public interface IUserCoreManagerRead
{
public User GetData();
}
public interface IUserCoreManagerReadWrite : IUserCoreManagerRead, IUserCoreMagagerWrite
{
}
public class UserCoreManager : IUserCoreManagerReadWrite
{
public User GetData()
{
return new User("abbo");
}
public void SetData(User user)
{
//...
}
}
public class Core
{
public IUserCoreManagerReadWrite UserCoreManager { get; set; }
}
public class AsyncCore
{
public IUserCoreManagerRead UserCoreManager { get; set; }
}
public class TheProgram
{
public void SynchronousWork()
{
Core core = new Core();
User user = core.UserCoreManager.GetData();
core.UserCoreManager.SetData(user);
}
public void AsyncWork()
{
AsyncCore core = new AsyncCore();
User user = core.UserCoreManager.GetData();
}
}
I'm designing a data layer for several classes, and I want each of these classes to follow a contract I set up with IMyDataItem:
public delegate void ItemChangedHandler(object sender, EventArgs e);
public interface IMyDataItem<T> {
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
}
That being done, I now want to include a base class that my other classes all inherit from.
How would I fix this base class?
public class MyDataItem : IMyDataItem<T> {
private const string TODO = "TODO: This has not been done.";
public const int NOT_SET = -1;
private bool changed;
internal int rowId;
public MyDataItem() {
changed = false;
rowId = NOT_SET;
}
public ItemChangedHandler OnChange;
internal void notify() {
changed = true;
if (OnChange != null) {
OnChange(this, new EventArgs());
}
}
public int RowID {
get { return rowId; }
set {
if (rowId != value) {
rowId = value;
notify();
}
}
}
public bool SaveNeeded { get { return changed; } }
public static virtual T Load() {
return default(T);
}
public virtual string Insert { get { return TODO; } }
public virtual string Select { get { return TODO; } }
public virtual string Update { get { return TODO; } }
public virtual int Save() {
changed = false;
return NOT_SET;
}
}
The errors are all in the second class MyDataItem (my base class):
Type or namespace name 'T' could not be found - on the first line where I declare my class.
I tried removing the errors by adding a where clause to the signature:
public class MyDataItem : IMyDataItem<T> where T : MyDataItem {
However, this presented me with the error:
Constraints are not allowed on non-generic declarations
Is there a way to do what I am after, or will I need to stick with simpler class designs?
When the base class is complete, other classes such as Location, Employee, and Record will inherit it.
Well to fix that particularly compile time error you would need:
public class MyDataItem<T> : IMyDataItem<T>
However, without knowing more about what you're trying to achieve, it's hard to recommend an alternative approach.
Why not drop the <T> from the interface and make it non-generic? The T is not used in the interface.
Otherwise, if you want the class to be generic, say
public class MyDataItem<T> : IMyDataItem<T>
But again, if T is not used, what's your reason to declare it?
What you are attempting to do is somewhat similar to what I've also done. I've wanted some generic code applicable to all my "data manager" instances but also wanted to apply stronger typing to them... In a similar fashion...
public interface iMyDataManager
{
stuff ...
}
public class MyDataManager<T> : iMyDataManager
{
implementation ... that I want common to all derived specific instances
}
public class MySpecificDataInstance : MyDataManager<MySpecificDataInstance>
{
continue with rest of actual implementations specific to this class.
}
I did not see any reason use generic in your implementation.
Secondary, are you sure about parameters of these functions:
string Insert { get; }
int Save();
string Select { get; }
string Update { get; }
Why Update and Insert returns parameters? Are you sure, you will able remember meaning of this within 2 months?