C# circular dependcy of two class, interfaces obj unable to create? - c#

I have 2 class projects. mqtt and Vm. so Vm class already referencing mqtt class and it works fine. now I want to creates a object of VM class in mqtt class project, which I understand create a circular dependency if I refer to the Vm class.
so I understand from google that I have to use interface, so I did and below is my code as follows.
mqtt class:
public class MqttControllerClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
if (Mcallback != null) // always null here **
Mcallback.call_queryEvent();
}
}
Vm class:
using MqttInterface;
namespace oadr2b_ven.ven
{
public class VenWrapper : resources.ISendReport,MqttInterface.InterfaceClass
{
public void call_queryEvent()
{
queryEvents();
}
}
}
now the interface class:
namespace MqttInterface
{
public interface InterfaceClass
{
void call_queryEvent();
}
}
so the issue is that if I don't declare in mqtt class a object the projects runs withour error but Mcallback != null is always null.
so I decide to create a interface object and I do this.
InterfaceClass Mcallback = new MqttControllerClass();
which throws me the below error
Cannot implicitly convert type 'MqttBroker.MqttControllerClass' to 'MqttInterface.InterfaceClass'. An explicit conversion exists (are you missing a cast?
I ask you guys I am new to c#. what am I dong wrong ? is there a better method ?
let me know. thanks.

I found the answer. all you have to do is assign the object of interfaced class using a callback method to the mqtt class.
namespace MqttInterface
{
public interface InterfaceClass
{
void call_queryEvent();
}
public void setCallbackHandler(InterfaceClass callbackHandler)
{
Mcallback = callbackHandler;
}// obj is assigned from Vm class
}

Your class definition is not implementing the needed interface:
public class MqttControllerClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
}
You should be using:
public class MqttControllerClass : InterfaceClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
}
Because if MqttControllerClassdoes not implement InterfaceClass, then you can't assign an object of type MqttControllerClass to a variable of type InterfaceClass.
This only solves the error you mentioned, but you're still dealing with badly designed code. Read on for further information.
I am wondering why you are taking this approach.
When you create an MqttControllerClass object, its Mcallback gets populated with another new MqttControllerClass object. Why???
First of all, this will create an infinite loop (every newly instantiated MqttControllerClasswill cause another new MqttControllerClass to be instantiated, thus creating an endless loop).
Disregarding the infinite loop, I don't even understand the justification for wanting to do this. It can make sense to have a class with the property of the same type, e.g. :
public class Person
{
public Person father;
public Person mother;
}
But it makes no sense to fill these properties with newly instantiated Person objects every time you instantiate a Person object.

Related

feeding a Type into a constructor

class Program{
void Apple(){
List<Banana> apple = new List<Banana> { (new Banana(Cucumber, 5)), (new Banana(Dates, 6)) };
}
}
class Banana{
public Banana(Type eggplant, int feijoa){
new eggplant(feijoa);
}
}
class Cucumber{
public Cucumber(int feijoa){
}
}
class Dates{
public Dates(int feijoa){
}
}
basically it feeds a bunch of information from the program class to the Banana class, which then filters that information and uses it to create instances of a bunch of different classes.
the problem is within the Program class, where even though it registers that a Type is needed to complete the Banana constructor, when given a Type, like Cucumber or Dates, it says giving a type there is not considered valid in the given context, so i would like some help with understanding how to fix it, thanks in advance.
while structuring my program this way might seem weird and inefficient, it's mostly to help simplify viewing and editing the front end of my program.
you should use typeof operator while passing argument to constructor.
Like :
List<Banana> apple = new List<Banana> { (new Banana(typeof(Cucumber), 5)), (new Banana(typeof(Dates), 6)) };
However inside constructor you need to use Activator.CreateInstance(typeof(T), object[] args) to instantiate either Cucumber or Banana objects.
Also you better consider redesigning your class like :
class Banana<T> where T: new(){
public Banana(int feijoa){
Activator.CreateInstance(typeof(T), new object[]{feijoa}
}
so your snippet would be changed to :
List<Banana> apple = new List<Banana> { (new Banana<Cucumber>(5)), (new Banana<Dates>(6)) };
To get the Type instance of Cucumber class you should use typeof(Cucumber). So your constructors should change to look like the following:
new Banana(typeof(Cucumber), 5)
new Banana(typeof(Dates), 6)
UPDATE
Here is some more context regarding your code. The constructor of the Banana type is actually incorrect.
It's not possible to call new on a type instance. What you're actually trying to do is instantiate an object of the passed eggplant parameter. There are multiple ways you can achieve that. But before going into details I recommend you to read about type constructors first.
Besides, it's a bit unclear what your intent is. What you're trying to do with the newly created instance. I would just assume for now that you're going to store that instance in some member variable, as follows:
public class Banana
{
private readonly object instance;
public Banana(Type eggplant, int feijoa)
{
this.instance = Activator.CreateInstancenew eggplant(feijoa, new object [] {feijoa});
}
}
Here I've used the Activator type which will create an instance of a given type if it'll find a matching constructor based on the parameters you've passed. Otherwise, an exception will be thrown.
While the above-mentioned approach would work, it's not ideal as it provides no type safety. So it would be great to use Generics here, but that is not possible with current code because of the requirement of having a constructor, which accepts a parameter. There is still a way to achieve that, but it'll require a lot of code changes, which is not directly related to your question. You can read more about Generics here.
While there are a lot of other options, I would ask whether it's really a requirement to have the design you've got here. Why not pass in the instances to the Banan class directly. To do that, you'll need to make sure there is a base class/interface, which all the potential parameters to the Banana constructor will extend. Here is an example you could go with:
class Program
{
void Apple()
{
List<Banana> apple = new List<Banana> { new Banana(new Cucumber(5)), new Banana(new Dates() { Feijoa = 6 }) };
}
}
class Banana
{
private readonly ICommon instance;
public Banana(ICommon instance)
{
this.instance = instance;
}
}
public interface ICommon
{
int Feijoa { get; set; }
}
class Cucumber : ICommon
{
public Cucumber(int feijoa)
{
this.Feijoa = feijoa;
}
public int Feijoa { get; set; }
}
class Dates : ICommon
{
public Dates()
{
}
public int Feijoa { get; set; }
}
Sorry, the provided context is not enought to be more specific. In the meantime, I tried to share as much as possible. I know, it may look scattered a bit.
Hope this helps.

Create a new class inherited from an existing class using reflection

How can I derive from a class through reflection? The following works for getting an existing instance and for creating a new instance of the class.
public class TreeViewSHWinstances {
[MenuItem("Reflect/CreateSHWinstances")]
static void Activate() {
Main();
}
static void Main() {
Assembly asm = typeof(UnityEditor.EditorWindow).Assembly;
Type wndType = asm.GetType ("UnityEditor.SceneHierarchyWindow");
// Grabs an existing instance if it exists and then sets the focus to it.
EditorWindow exstWnd = EditorWindow.GetWindow (wndType);
// Always create a new instance regardless if one already exists.
EditorWindow newWnd = (EditorWindow)Activator.CreateInstance (wndType);
}
}
This is what I actually want to do, but obviously the assembly is not yet loaded and when I have tried to acquire it form the above class I get an error that says it is not a Type even though I'm requesting wndType.
// THIS IS NOT INTENDED TO NOR DOES IT WORK.
public MySceneHierarchyWindow : UnityEditor.SceneHierarchyWindow {
}
My guess was to use Emit in some way, but I after experimenting with it I'm not sure it is the right direction.

Return non null Interface object from GenericClass<T> or better programming pattern?

I have a Generic class as below.
Subscriber<T> where T : class
{
public T callback {get; set;}
public USER User {get; set;}
}
T is really an interface for the callback being passed in and around. However as you know when I go to use this Null Reference Exception is thrown. So I go and search stack'O to create an instance of interface T , as you know I can't create an instance of an interface (duh) but I thought maybe there was a way around this. I am using WCF and would like to store the callback object but do it generically as the Subscriber method could be used for other callback contracts. Should I store as object and on the get cast to type T ?
private object _callback;
public object Callback
get
{
return (T)_callback;
}
set
{
_callback = value;
}
EDIT:
I create this object in my Client and I pass this into my Service Subscribe method. The callback cannot be set in the client because I do not have a callback object there (at least that I know of). So in my Subscribe method of the Service I have Subscriber.Callback = OperationContext.Current;
Perhaps my design pattern for storing this value in the class is wrong - how to do it ?
EDIT: Code Posted per Daniels Request. Comments in code indicate where issues reside. In the Subscribe method of the WCFServer - I get NRE. of course.
In the Form where the user is created - I can not set the Callback to a new one as it is not created yet and is only an interface. How do I create the User Class in my Client Form, with the callback parameter so it can be used in my Server to store the callback. Should I just declare it as object and cast to T? Or is my logic here wrong - any help is appreciated!
CLIENT FORM:
public partial class Form1 : Form
{
Form1()
{
this.ServiceSubscriber = new WCF.Subscriber<WCF.Interfaces.IDataCallback>();
// Problem occurs that I cant set the callback here.
// this.ServiceSubscriber.Callback
}
public void WCFClientLogin(WCF.Subscriber<WCF.Interfaces.IDataCallback> subscriber)
{
if (WCFClient == null)
{
WCFClient = new WCF.ClientProxy();
}
WCFClient.StartClient(subscriber);
}
}
INTERFACE :
interface IDataCallBack
{
[OperationContract(IsOneWay=true)]
void Subscribe(WCF.Subscriber<WCF.Interfaces.IDataCallback> subscriber);
}
SUBSCRIBER CLASS :
public class Subscriber<T> : ISubscriber<T> where T : class
{
public T Callback {get; set;}
public Guid UniqueIdentifier {get; set;}
public Subscriber(T callback)
{
this.UniqueIdentifier = Guid.NewGuid();
this.Callback = callback;
}
}
WCF SERVICE :
public void Subscribe(Subscriber<IDataCallback> registrant)
{
lock (_syncSubscribe)
{
try
{
IDataCallback callback = OperationContext.Current.GetCallbackChannel<IDataCallback>();
// RegisteredUser is Dictionary<Guid, IDataCallback>
// I can't set it here either because I get null reference exception.
RegisteredUser[registrant.UniqueIdentifier].Callback = callback;
}
catch(Exception e) // TODO: More Explicit Catch
{
OnServerException(e);
}
}
}
"I can't create an instance of an interface (duh) but I thought maybe there was a way around this" — no, there is no way around this. You cannot deserialize interfaces, unless they are "special" with known default implementations (e.g. IList<T>), and even then whether it will work will depend on your exact context.
The receiving end needs to know the type used to implement the interface, otherwise it has no way to ensure the deserialized object will behave the same as the serialized object. Just fix your contract so it uses a concrete type instead of an interface.

No constructors defined

I have some code base which has is calling the following:
SetHazardDataService();
namespace Analytics.Foo.DataServices
{
class HDB:IDataService
{
}
}
With a member function declared in another class/file
using Analytics.Foo.DataServices
public void MyDataService()
{
var DbDataSvc = new HDB();
}
originally, I see the same definition used elsewhere but with (no idea if that works):
protected void MyDataService()
I included the public method in my class
I'm now trying to recreate that functionality, but I get the following issue:
The type Analytics.Foo.DataServices.HDB' has no constructors defined
I'm not sure what the issue is - any suggestions for why this is the case. There is no constructor that I can see. Plus I'm not able to see the other code working/but it doesn't give the same issue.
You need to create a constructor to class HDB, like this:
namespace Analytics.Foo.DataServices
{
class HDB:IDataService
{
public HDB()
{
}
}
}

Do I need type checking for a C# object factory to call the appropriate methods?

Given the following pseudo C# code:
class BigMessage : Message { }
class SmallMessage : Message { }
abstract class Message
{
static public Message Factory()
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
if (randomNumber > 50)
{
return new BigMessage();
}
else
{
return new SmallMessage();
}
}
}
class Worker
{
public void Comprehend(BigMessage bm)
{
}
public void Comprehend(SmallMessage bm)
{
}
public void start() {
Message msg = Message.Factory();
Comprehend(msg);
}
}
If I ask the Factory to give me a random Message object inherited from Message (e.g. Big or Small Message), and I would like the Comprehend methods in the Worker class to act on the type of message given using overloading (the proper OO way, rather than explicit type checking), why do I get the following two types of errors and can you help me understand what I am doing wrong?
The best overloaded method match for 'Worker.Comprehend(BigMessage)' has some invalid arguments.
cannot convert from 'Message' to 'BigMessage'
Ultimately I expect the Factory to provide me with an object inherited from Message, who's type I do not know in advance. I do need to act differently given the different type returned. Inheritance is very helpful in this scenario as the abstract class provides much useful functionality shared with it's child classes.
.NET 4.5 is used.
Thanks in advance!
The reason that you get the conversion error is that you cannot convert a "Message" type to a concrete "BigMessage" or "SmallMessage". It should be the other way around where you have Comprehend(Message msg) and that allows the method to accept any inherited objects.
In addition, what I think you are trying to achieve is polymorphism. I believe to correctly create your objects, your base abstract class Message should have a method called "Comprehend" and in your worker process, you call msg.Comprenhend(). This way, as you get more additional message types, you are not adding additional comprehend methods to your worker class for each message. By leveraging OOP and inheritance, you let the object decide how they comprehend themselves.
sample code below:
abstract class Message
{
abstract void Comprehend();
public static Message Factory(){... code here to return message }
}
class BigMessage : Message
{
public void Comprehend()
{
//do work here
}
}
class SmallMessage : Message
{
public void Comprehend()
{
//do work here
}
class Worker
{
public void Start()
{
var msg = Message.Factory();
msg.Comprehend();
}
}
Hope this helps!

Categories