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();
}
}
Related
This is my interface:
public interface ISocialService<T> where T : ISocialModel
{
public Task<List<T>> GetPosts();
}
I have 2 implementations of this interface.
This is how I try to register them
services.AddScoped<ISocialService<RedditPost>, RedditService>();
services.AddScoped<ISocialService<HackerNewsModel>, HackerNewsService>();
And finally this is how I try to resolve them.
public ScrapeJob(IEnumerable<ISocialService<ISocialModel>> socialServices)
{
_socialServices = socialServices;
}
However socialServices is empty.
I think the problem lies in ISocialModel.
Anyone got suggestions how can I register or resolve them properly?
The reason why I want to use a generic interface is I want to inject specific service into a controller like this:
public HackerNewsController(ISocialService<HackerNewsModel> socialService)
{
_socialService = socialService;
}
The problem is you have injected generic interface IEnumerable<ISocialService<ISocialModel>> but you don't have any classes that implement ISocialService<ISocialModel> instead you have ISocialService<T> implementation in classes.
so we need to update the code following way for example
public interface ISocialModel
{
}
public class RedditModel : ISocialModel
{
}
public interface ISocialService
{
Task<List<ISocialModel>> GetPosts();
}
public interface ISocialService<T>: ISocialService where T : ISocialModel
{
Task<List<T>> GetPosts();
}
public abstract class SocialServiceBase<T> : ISocialService<T> where T : ISocialModel
{
async Task<List<ISocialModel>> ISocialService.GetPosts()
{
var posts = await GetPosts();
return posts.Cast<ISocialModel>().ToList();
}
public abstract Task<List<T>> GetPosts();
}
public class RedditSocialService : SocialServiceBase<RedditModel>
{
public override Task<List<RedditModel>> GetPosts()
{
//TODO: past your implementation here
}
}
so in registration now you can write following code
services.AddScoped<ISocialService, RedditService>();
services.AddScoped<ISocialService, HackerNewsService>();
and later in class you can use like that
class ScrapeJob
{
private IEnumerable<ISocialService> _socialServices;
public ScrapeJob(IEnumerable<ISocialService> socialServices)
{
_socialServices = socialServices;
}
public async Task DoScrapeJob()
{
foreach( var service in _socialServices)
{
var posts = await service.GetPosts();
}
}
}
Have a look at this link:
https://www.stevejgordon.co.uk/asp-net-core-dependency-injection-registering-multiple-implementations-interface
You may need to register ISocialModel for both in order for it to be recognized as a collection of IEnumerable:
e.g.
services.AddScoped<ISocialModel, RedditService>();
services.AddScoped<ISocialModel, HackerNewsService>();
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
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
I have this class called BluetoothDeviceInfo from 32feet library to handle, obviously, Bluetooth related stuff.
I have created my program and it worked. However, I need to add some information to a "more complete", lets say, class which also carries GPS information.
So what I did was to created a new class MyDeviceInfo and derive it from BluetoothDeviceInfo as the code below.
Base* (which I don't have control on)
namespace InTheHand.Net.Sockets
{
public class BluetoothDeviceInfo : IComparable
{
public BluetoothDeviceInfo(BluetoothAddress address);
public bool Authenticated { get; }
public ClassOfDevice ClassOfDevice { get; }
public bool Connected { get; }
public BluetoothAddress DeviceAddress { get; }
public string DeviceName { get; set; }
.
.
.
Derive*
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
public MyDeviceInfo(BluetoothAddress address) : base(address)
{
gpsSignal = false;
}
#region Properties
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
And I substituted all my BluetoothDeviceInfo types in my code with MyDeviceInfo types.
Everything seems working except this part.
This particular method called Client.DiscoverDevice() returns a list of Bluetooth devices available in the type BluetoothDeviceInfo. And since this is of a type base class, it doesn't make sense that I would cast it to a variable of my derive class MyDeviceInfo and I can't get past this point since I need the list of devices. Even though sounding wrong I tried to cast it using this code (which obviously didn't work)
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (IEnumerable<MyDeviceInfo>)cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...
Since this logic doesn't fit into inheritance I thought of composition. However, this isn't quite fit the composition line of thought such as object Bird can have flying functionality of type Airplane but not the whole lot cuz I actually need my driven class include all the functionality of BluetoothDeviceInfo.
I want to understand the big picture here and what would be approach to do such a thing.
Will be happy to hear you thoughts and guides on this.
Cheers
Try this:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b.DeviceAddress)).ToList();
You may need to provide a MyDeviceInfo constructor that takes a BluetoothDeviceInfo and copies all the properties.
Update
The code then becomes:
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
MyDeviceInfo(BluetoothDeviceInfo btInfo)
{
this.Authenticated = btInfo.Authenticated;
this.ClassOfDevice = btInfo.ClassOfDevice;
this.Connected = btInfo.Connected;
this.DeviceAddress = btInfo.DeviceAddress;
this.DeviceName = btInfo.DeviceName;
}
public MyDeviceInfo(string address) : base(address)
{
gpsSignal = false;
}
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
And you use it like this:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b)).ToList();
Application note.
To the extent that inheritance works, use that. See Ned Stoyanov's answer. My answer below should only be used if the library class is sealed.
Problem #1 - Library class was sealed and wasn't dependent on an interface, therefore I cannot substitute it with my own class.
Solution: Make an interface anyway.
public interface IMyDeviceInfo : IComparable
{
BluetoothDeviceInfo(BluetoothAddress address);
bool Authenticated { get; }
ClassOfDevice ClassOfDevice { get; }
bool Connected { get; }
BluetoothAddress DeviceAddress { get; }
string DeviceName { get; set; }
...
}
Problem #2 - How can I stuff the library class under my interface?
Solution: Make an adapter.
public class DeviceInfoAdapter : IMyDeviceInfo
{
private BluetoothDeviceInfo m_theRealStuff;
// Allow yourself to bypass the abstraction to
// get down to the real object, because it may
// just be unavoidable in some cases.
// You may also mark it [Obsolete] or comment it out
// until you encounter a real need for it.
internal BluetoothDeviceInfo TheRealStuff
{
get { return m_theRealStuff; }
}
// Constructor. If the real stuff has been created by someone else.
public DeviceInfoAdapter(BluetoothDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// Constructor. A knock-off copy of the real stuff constructor.
public DeviceInfoAdapter(BluetoothAddress address)
{
m_theRealStuff = new BluetoothDeviceInfo(address);
}
// Imitate all properties and methods on the real stuff.
public bool Authenticated
{
get
{
return m_theRealStuff.Authenticated;
}
}
// ...
// Basically, for every publicly-accessible method or property,
// you just call the real stuff.
}
Problem #3 - How do I add extra properties to it?
Solution: Make a decorator.
public interface IMyDeviceInfoExtra : IMyDeviceInfo
{
bool GpsSignal { get; set; }
}
public class MyDeviceInfoWithGps : IMyDeviceInfoExtra
{
private IMyDeviceInfo m_theRealStuff;
private bool m_gpsSignal;
public MyDeviceInfoWithGps(IMyDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// the same thing again ... lots of code duplications
// The only new member here
public bool GpsSignal
{
get { return m_gpsSignal; }
set { m_gpsSignal = value; }
}
}
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?