Thanks to NHMountainGoat for an answer!
Implementing Interface looks a good choice so we have only the 'needed' method instanciated.
It looks like this now:
EDIT
class Machine
{
//REM: MachineConnexion is a link to the main server where asking the data
internal linkToPLC LinkToPLC;
public IlinkToPLC ILinkPLC;
public interface IlinkToPLC//Interface to linkPLC
{
Int16 MachineNumIS { get; set; }
}
internal class linkToPLC : IlinkToPLC
{
private Int16 Act_MachineNum;
private List<string> genlnkPLCCanvas;
private List<string> genlnkPLCworkingwith;
static private List<string> ListSymbolNoExist;
private string[] ListToPLClnk = {
"GlobalFolder.PMachine[{0}].",
"GlobalFolder.PMachine[{0}].STATE.",
"GlobalFolder.Machine[{0}].",
"GlobalFolder.Machine[{0}].STATE.",
};
public linkToPLC()//ctor
{
genlnkPLCCanvas = new List<string>(ListToPLClnk);
genlnkPLCworkingwith = new List<string>(ListToPLClnk);
ListSymbolNoExist = new List<string>();
Act_MachineNum = MachineNumIS;
}
public Int16 MachineNumIS { get { return (Int16)ReadWriteMachine("data"); } set { ReadWriteMachine("data", value); } }
public string ValueExist(string ValueToreach, bool WorkingDATA = false)
{
if (!WorkingDATA)
{
for (int inc = 0; inc < genlnkPLCworkingwith.Count; inc++)
{
string StrValueToReach = genlnkPLCworkingwith[inc] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[inc] + ValueToreach);
}
}
else if (WorkingDATA)
{
string StrValueToReach = genlnkPLCworkingwith[10] + ValueToreach;
if (MachineConnexion.SymbolExists(StrValueToReach))
{
ListSymbolNoExist.Clear();
return StrValueToReach;
}
else ListSymbolNoExist.Add(genlnkPLCworkingwith[10] + ValueToreach);
}
if (ListSymbolNoExist.Count != 0)
{
string ErrorList = "";
for (int inc = 0; inc < ListSymbolNoExist.Count; inc++)
{
ErrorList = string.Concat(ErrorList + "Num: " + inc.ToString() + " " + ListSymbolNoExist[inc].ToString() + "\n");
}
Console.WriteLine("Error" + ErrorList);
}
return null;
}
public object ReadWriteMachine(string VariableName, object DataToWrite = null, bool WorkingDATA = false)
{
string valueToFind = "";
if (ValueExist(VariableName) != "FALSE")
{
if (DataToWrite != null) { MachineConnexion.WriteSymbol(valueToFind, DataToWrite); }
return MachineConnexion.ReadSymbol(valueToFind);
}
return VariableName;
}
}
public Machine() //constructor
{
LinkToPLC = new linkToPLC();
}
}
And It doesn't work telling me that the reference object is not defined to an instance of the object..... in the line : Machine() LinkToPLC = new linkToPLC();//REM I found the bug, it was me ;o)) 24112016
//REM 24112016
What are the main differences between those two concept: static Instance and Interface?
Example:
class Program
{
static void Main(string[] args)
{
ITestInterface InterInstance = new TestInterface();
//test Interface
bool value1 = true;
value1 = InterInstance.invert(value1);
InterInstance.print(value1);
//test Instance static
TestStaticInstance staticInstance = new TestStaticInstance();
staticInstance.Instance.invert(value1);
staticInstance.Instance.print(value1);
Console.ReadKey();
}
}
class TestInterface : ITestInterface
{
public bool invert(bool value)
{
return !value;
}
public void print(bool value)
{
Console.WriteLine(value.ToString()+"\n");
}
private void methodX()
{ }
}
interface ITestInterface
{
bool invert(bool value);
void print(bool value);
}
public class TestStaticInstance
{
public TestStaticInstance Instance;
public TestStaticInstance()
{
Instance = this;
}
internal bool invert(bool value)
{
return !value;
}
internal void print(bool value)
{
Console.WriteLine(value.ToString());
}
}
Thanks
Can you structure your other classes to take an instance of the link class? See:
/// <summary>
/// just a stub to demonstrate the model
/// </summary>
internal class Machine
{
public string ReadData() { return "this is data"; }
public void WriteData(string data) { Console.WriteLine(data); }
}
internal interface IMachineDataAccessor
{
string Read();
void Write(string data);
}
class LinkClass : IMachineDataAccessor
{
protected Machine _machine;
public LinkClass(Machine machine)
{
_machine = machine;
}
public void DoMyWork()
{
// insert work somewhere in here.
string dataFromMachine = Read();
Write("outbound data");
}
public string Read()
{
return _machine.ReadData();
}
public void Write(string data)
{
_machine.WriteData(data);
}
}
class PersistentClass
{
IMachineDataAccessor _machineImpl;
public PersistentClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
class StateClass
{
IMachineDataAccessor _machineImpl;
public StateClass(IMachineDataAccessor machineAccessImplementation)
{
_machineImpl = machineAccessImplementation;
}
public void DoMyWork()
{
string dataFromMachine = _machineImpl.Read();
// insert work here. Or anywhere, actually..
_machineImpl.Write("outbound data");
}
}
static void Main(string[] args)
{
LinkClass link = new LinkClass(new Machine());
PersistentClass persistent = new PersistentClass(link as IMachineDataAccessor);
StateClass state = new StateClass(link as IMachineDataAccessor);
persistent.DoMyWork();
state.DoMyWork();
link.DoMyWork();
}
Related
Trying to analyze this code with Roslyn.
public class MyClass
{
#region FirstRegion
public void MyMethod()
{
}
#endregion
#region SecondRegion
public void MyMethod1()
{
}
private static void MyMethod3()
{
}
#endregion
}
At first I want to break it on regions and then to look what function is declared in each region.
var syntaxRoot = tree.GetRoot();
var regions = syntaxRoot.GetRegions();
foreach (var item in regions)
{
var publicFunctions = syntaxRoot.GetFunctions(item.FullSpan, Modificators.Public);
}
I thought that it can be done by specifying TextSpan
Region region = new Region();
region.Identifier = rawRegions[i].GetText().ToString();
region.FullSpan = new TextSpan(rawRegions[i].FullSpan.Start, rawRegions[i + 1].FullSpan.End - rawRegions[i].FullSpan.Start);
regions.Add(region);
But at the end i get that first regions contains two public methods, second region only one public method. It seems that in my case TextSpan is wrong, but why? How to fix this?
Program.cs
public class Modificators
{
public const string Public = "public";
public const string Private = "private";
public const string Protected = "protected";
}
public class Region
{
public string Identifier { get; set; }
public TextSpan FullSpan { get; set; }
}
public static class SyntaxExtensions
{
public static List<MethodDeclarationSyntax> GetFunctions(this SyntaxNode syntaxNode, TextSpan textSpan, string modifiers)
{
return syntaxNode.DescendantNodes(textSpan, null, false)
.OfType<MethodDeclarationSyntax>()
.Where(modificator => modificator.Modifiers.Any(x => x.Text.Contains(modifiers.ToString())))
.ToList();
}
public static List<Region> GetRegions(this SyntaxNode syntaxNode)
{
List<Region> regions = new List<Region>();
var rawRegions = syntaxNode.DescendantNodes(null, true).Where(x => x.RawKind == 8552 || x.RawKind == 8553).ToList();
for (int i = 0; i < rawRegions.Count; i = i + 2)
{
Region region = new Region();
region.Identifier = rawRegions[i].GetText().ToString();
region.FullSpan = new TextSpan(rawRegions[i].FullSpan.Start, rawRegions[i + 1].FullSpan.End - rawRegions[i].FullSpan.Start);
regions.Add(region);
}
return regions;
}
}
class Program
{
static void Main(string[] args)
{
var tree = CSharpSyntaxTree.ParseText(#"
public class MyClass
{
#region FirstRegion
public void MyMethod()
{
}
#endregion
#region SecondRegion
public void MyMethod1()
{
}
private static void MyMethod3()
{
}
#endregion
}");
var syntaxRoot = tree.GetRoot();
var regions = syntaxRoot.GetRegions();
foreach (var item in regions)
{
var publicFunctions = syntaxRoot.GetFunctions(item.FullSpan, Modificators.Public);
}
}
}
fans of beautiful code.
I would like to ask my question by two ways. May be it will be useful to understand me.
1) There is code of 2 classes. One of them is nested. Nested class is used to get access to private fields of other one. I would like to get inherit class B:A{class BUnit:AUnit{}} which has the same functional but else has some more methods and fields in B and BUnits classes. How it can be done?
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a.Add();
a.Add();
bool res=a[0].Rename("1");//res=true;
res = a[1].Rename("1");//res= false;
Console.ReadKey();
}
}
class A
{
private List<AUnit> AUnits;
public AUnit this[int index] {get {return AUnits[index];}}
public A()//ctor
{
AUnits = new List<AUnit>();
}
public void Add()
{
this.AUnits.Add(new AUnit(this));
}
public class AUnit
{
private string NamePr;
private A Container;
public AUnit(A container)//ctor
{
NamePr = "Default";
this.Container = container;
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.AUnits)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
2) There is two very similar “things” – Class A and Class B. Is it possible to separate their common part, and then “inherit” this two “things” from it ? For example, I would like add some methods like GetUnitsCount() or RemoveUnit() and this methods are common for both. So I should “CopyPaste” this method to A and B but it is not good idea. It will be better to change their common part one time in one place. There is no important how it can be done – inheriting or interfaces or anything else. Important - how?
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Add();
a[0].objB.Add();
a[0].objB.Add();
a[0].objB[0].Val1 = 1;
int res = a[0].objB[0].Val1 + a[0].objB[0].Val2;
Console.ReadKey();
}
}
class A
{
private List<AUnit> Units;
public AUnit this[int index] {get {return Units[index];}}
public A()//ctor
{
Units = new List<AUnit>();
}
public void Add()
{
this.Units.Add(new AUnit(this));
}
public class AUnit
{
private string NamePr;
private A Container;
public B objB;
public AUnit(A container)//ctor
{
NamePr = "Default";
this.Container = container;
this.objB = new B();
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (AUnit unt in this.Container.Units)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
class B
{
private List<BUnit> Units;
public BUnit this[int index] { get { return Units[index]; } }
public B()//ctor
{
Units = new List<BUnit>();
}
public void Add()
{
this.Units.Add(new BUnit(this));
}
public class BUnit
{
private string NamePr;
private B Container;
public int Val1{get;set;}
public int Val2{get;set;}
public BUnit(B container)//ctor
{
NamePr = "Default";
this.Container = container;
this.Val1 = 10;
this.Val2 = 17;
}
public string Name { get { return this.NamePr; } }
public Boolean Rename(String newName)
{
Boolean res = true;
foreach (BUnit unt in this.Container.Units)
{
if (unt.Name == newName) res = false;
}
if (res) this.NamePr = String.Copy(newName);
return res;
}
}
}
Thank you for your attentions.
To answer your first question, the only thing you need to to to have BUnit inherit from AUnit is to qualify AUnit:
public class BUnit : A.AUnit
{
....
}
from there I believe your question is about basic inheritance which works no differently for nested classes. Nested classes are purely for organization - they are not inherited when you inherit the "containing" class.
I am a beginner to C# programming.
When I run this program, the eventhandler named - newMessagePublishedEventHandler of the class MessagePool is always null while executing the OnNewMessagePublished() function of the same class.
Can anyone please tell me why? and also how could I resolve this?
namespace ConsoleApp
{
public class MessageEventArgs : System.EventArgs
{
private int publisherId;
private string message;
public MessageEventArgs(int publisherId, string messageText)
{
this.publisherId = publisherId;
this.message = messageText;
}
public int PublisherId
{
get { return publisherId; }
}
public string Message
{
get { return message; }
}
}
public class Publisher
{
private int publisherId;
public Publisher(int publisherId)
{
this.publisherId = publisherId;
}
public int PublisherId
{
get { return publisherId; }
}
public void Publish(string message)
{
MessagePool.GetInstance().Publisher_PostMessage(this.publisherId, message);
Console.WriteLine("published message - " + message);
}
}
public class MessagePool
{
private static MessagePool theOnlyInstanceOfMessageBroker;
public static MessagePool GetInstance()
{
if (theOnlyInstanceOfMessageBroker == null)
{
return new MessagePool();
}
else
{
return theOnlyInstanceOfMessageBroker;
}
}
private MessagePool()
{
}
private EventHandler newMessagePublishedEventHandler;
public event EventHandler NewMessagePublished
{
add
{
newMessagePublishedEventHandler += value;
}
remove
{
newMessagePublishedEventHandler -= value;
}
}
public void Publisher_PostMessage(int publisherId, string message)
{
DateTime publishedTime = DateTime.Now;
this.OnNewMessagePublished(publisherId, message);
}
private void OnNewMessagePublished(int publisherId, string message)
{
MessageEventArgs eventArgs = new MessageEventArgs(publisherId, message);
if (newMessagePublishedEventHandler != null)
{
newMessagePublishedEventHandler(this, eventArgs);
}
}
}
public class Subscriber
{
private int subscriberId;
public Subscriber(int subscriberId)
{
this.subscriberId = subscriberId;
this.SubscribeToMessagebroker();
}
public int SubscriberId
{
get { return subscriberId; }
}
private void SubscribeToMessagebroker()
{
MessagePool.GetInstance().NewMessagePublished -= Subscriber_NewMessageArrived;
MessagePool.GetInstance().NewMessagePublished += Subscriber_NewMessageArrived;
}
private void Subscriber_NewMessageArrived(object sender, EventArgs eventArgs)
{
if (eventArgs != null && eventArgs is MessageEventArgs)
{
var data = eventArgs as MessageEventArgs;
if (data != null)
Console.WriteLine("Recieved message : '" + data.Message + "' from " + data.PublisherId);
}
}
}
class Program
{
static void Main(string[] args)
{
Subscriber subscriber = new Subscriber(1);
Publisher publisher = new Publisher(1001);
publisher.Publish("Hey man.. whats up?");
Console.ReadLine();
}
}
}
MessagePool is not a proper Singleton, you are always returning a new MessagePool.
public class MessagePool
{
private static MessagePool theOnlyInstanceOfMessageBroker;
private static object _syncRoot = new object();
public static MessagePool GetInstance()
{
if (theOnlyInstanceOfMessageBroker == null)
{
lock(_syncRoot)
{
if (theOnlyInstanceOfMessageBroker == null)
theOnlyInstanceOfMessageBroker = new MessagePool();
}
}
return theOnlyInstanceOfMessageBroker;
}
private MessagePool()
{
}
//...
}
Why is it not possible to have this ?
[ConfigurationProperty(typeof(CCfgElement).ToString())]
I get the error:
Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
here is my code
public class CConfigElement<T> : ConfigurationElement
{
}
public class CConfigSection<CCfgElement> : ConfigurationSection where CCfgElement : CConfigElement<CCfgElement>
{
// Create a element.
[ConfigurationProperty(typeof(CCfgElement).ToString())]
public CCfgElement Element
{
get { return (CCfgElement)this[typeof(CCfgElement).ToString()]; }
set { this[typeof(CCfgElement).ToString()] = value; }
}
}
I do not think there is any workarounds but
can anybody tell me how to add a section lement with code?
Søren
I found a kind of solution my self
here is my code
// create the DataModel in your MainWindow or App
// CTestDataModel t = new CTestDataModel();
public class CTestDataModel
{
CTestValues _Cfg;
// Create values to save in cofig
public class CTestValues : ConfigurationElement
{
[ConfigurationProperty("Param", DefaultValue = 11, IsRequired = true)]
public int Param
{
get { return (int)this["Param"]; }
set { this["Param"] = value; }
}
[ConfigurationProperty("Param1", DefaultValue = "22", IsRequired = true)]
public double Param1
{
get { return (double)this["Param1"]; }
set { this["Param1"] = value; }
}
[ConfigurationProperty("Time", IsRequired = true)]
public DateTime Time
{
get { return (DateTime)this["Time"]; }
set { this["Time"] = value; }
}
}
public CTestDataModel()
{
// load config
_Cfg = CConfiguration.Element<CTestValues>();
// Use values
int t = _Cfg.Param;
_Cfg.Param = 5;
_Cfg.Param1 = 6;
_Cfg.Time = new DateTime(1962, 10, 10);
}
}
public class CConfigSection<CCfgElement> : ConfigurationSection where CCfgElement : ConfigurationElement
{
// Create a element.
[ConfigurationProperty("Element")]
public CCfgElement Element
{
get { return (CCfgElement)this["Element"]; }
set { this["Element"] = value; }
}
}
public static class CConfiguration
{
static Configuration config = null;
static AppSettingsSection appSettings = null;
static CConfiguration()
{
config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
appSettings = config.AppSettings;
AppDomain.CurrentDomain.ProcessExit += CConfiguration_Dtor;
}
private static void CConfiguration_Dtor(object sender, EventArgs e)
{
config.Save(ConfigurationSaveMode.Modified, true);
}
// Uses sections
private static String MakeSectionName(String name)
{
return name.Replace('+', '.');
}
public static void RemoveSection(Type T)
{
try
{
String name = MakeSectionName(T.ToString());
config.Sections.Remove(name);
}
catch (Exception)
{
return;
}
}
public static T Element<T>() where T : ConfigurationElement
{
try
{
return Section<T>().Element;
}
catch (Exception ex)
{
Debug.WriteLine(typeof(T).ToString()+" error: "+ex.Message);
throw ex;
}
}
public static CConfigSection<T> Section<T>() where T : ConfigurationElement
{
try
{
return Section(typeof(T).ToString(), new CConfigSection<T>()) as CConfigSection<T>;
}
catch (Exception ex)
{
Debug.WriteLine(typeof(T).ToString()+" error: "+ex.Message);
throw ex;
}
}
public static ConfigurationSection Section(String name, ConfigurationSection section)
{
try
{
name = MakeSectionName(name);
ConfigurationSection cs = config.Sections.Get(name);
if (cs == null)
{
config.Sections.Add(name, section);
return section;
}
else
return cs;
}
catch (Exception)
{
config.Sections.Remove(name);
config.Sections.Add(name, section);
return section;
}
}
// Uses AppSettings
public static bool Exist(String key)
{
return appSettings.Settings[key] != null;
}
public static string Read(String key, string Default = "")
{
if (Exist(key))
return appSettings.Settings[key].Value;
return Default;
}
public static void Write(string key, string value)
{
if (Exist(key))
appSettings.Settings.Remove(key);
appSettings.Settings.Add(key, value);
}
public static void Remove(string key)
{
if (Exist(key))
appSettings.Settings.Remove(key);
}
public static new string ToString()
{
StringBuilder sb = new StringBuilder();
// Get the settings collection (key/value pairs).
if (appSettings.Settings.Count != 0)
{
foreach (string key in appSettings.Settings.AllKeys)
{
string value = appSettings.Settings[key].Value;
sb.Append(String.Format("Key: {0} Value: {1}\r\n", key, value));
}
}
return sb.ToString();
}
}
This is what I came up with, but it feels bloated and well, untidy. And I don't like that I have created an instance of each class just to get the right one.
class FileHasher
{
private readonly List<IHasher> _list;
public FileHasher()
{
_list = new List<IHasher>();
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
if(typeof(IHasher).IsAssignableFrom(type) && type.IsClass)
_list.Add((IHasher) Activator.CreateInstance(type));
}
}
public HashReturn GetHashFromFile(string file, HashFileType hashType)
{
var hashReturn = new HashReturn();
IHasher iHasher = _list.Find(hasher => hasher.HashType == hashType);
hashReturn.Hash = iHasher.FileToHash(file);
return hashReturn;
}
public HashReturn GetHashFromString(string str, HashFileType hashType)
{
var hashReturn = new HashReturn();
IHasher iHasher = _list.Find(hasher => hasher.HashType == hashType);
hashReturn.Hash = iHasher.StringToHash(str);
return hashReturn;
}
}
internal class HashReturn
{
public Exception Error { get; set; }
public string Hash { get; set; }
public bool Success { get; set; }
}
enum HashFileType
{
CRC32,
MD5
}
internal interface IHasher
{
HashFileType HashType { get; }
string FileToHash(string file);
string StringToHash(string str);
}
class MD5Hasher : IHasher
{
public HashFileType HashType { get { return HashFileType.MD5; } }
public string FileToHash(string file)
{
return "";
}
public string StringToHash(string str)
{
return "";
}
}
class CRC32Hasher : IHasher
{
public HashFileType HashType { get { return HashFileType.CRC32; } }
public string FileToHash(string file)
{
return "";
}
public string StringToHash(string str)
{
return "";
}
}
MEF solves this nicely for you.
http://mef.codeplex.com/
It is included in .NET 4.