Following this post and this other post here we are with another review request. The code that follows contains the definition of logic gates (binary gates like the AND, OR gate, and unary gates like NOT). They are a part of an open-source application I have started to build. I'm following the Observer pattern to build the application.
As always, feel free to be merciless with the review, throw me anything you can find:
Gate.cs
public abstract class Gate : IObserver<Pin>, ILogicComponent
{
// fields
private readonly Guid _id = Guid.NewGuid();
private Pin _output;
private IDisposable _outputUnsubscriber;
// properties
public Guid Id
{
get
{
return _id;
}
}
public string Code { get; set; }
public string Label { get; set; }
public Pin Output
{
get
{
return _output;
}
protected set
{
_output = value;
if (_outputUnsubscriber != null)
{
_outputUnsubscriber.Dispose();
}
if (_output != null)
{
_outputUnsubscriber = _output.Subscribe(this);
}
_output.Notify(_output);
}
}
public abstract IEnumerable<PinValue> InputValues { get; }
public IEnumerable<PinValue> OutputValues
{
get
{
PinValue[] result = new PinValue[0];
if (Output != null)
{
result = new PinValue[] { Output.Value };
}
return result;
}
}
// methods
public abstract void OnCompleted();
public abstract void OnError(Exception error);
public abstract void OnNext(Pin value);
}
UnaryGate.cs
public abstract class UnaryGate : Gate
{
// variables
private Pin _input;
private IDisposable _inputUnsubscriber;
// properties
public Pin Input
{
get
{
return _input;
}
protected set
{
_input = value;
if (_inputUnsubscriber != null)
{
_inputUnsubscriber.Dispose();
}
if (_input != null)
{
_inputUnsubscriber = _input.Subscribe(this);
}
_input.Notify(_input);
}
}
public override IEnumerable<PinValue> InputValues
{
get
{
var result = new PinValue[0];
if (Input != null)
{
result = new PinValue[] { Input.Value };
}
return result;
}
}
}
BinaryGate.cs
public abstract class BinaryGate : Gate
{
// variables
private Pin _input1;
private Pin _input2;
private IDisposable _input1Unsubscriber;
private IDisposable _input2Unsubscriber;
// properties
public Pin Input1
{
get
{
return _input1;
}
protected set
{
_input1 = value;
if (_input1Unsubscriber != null)
{
_input1Unsubscriber.Dispose();
}
if (_input1 != null)
{
_input1Unsubscriber = _input1.Subscribe(this);
}
_input1.Notify(_input1);
}
}
public Pin Input2
{
get
{
return _input2;
}
protected set
{
_input2 = value;
if (_input2Unsubscriber != null)
{
_input2Unsubscriber.Dispose();
}
if (_input2 != null)
{
_input2Unsubscriber = _input2.Subscribe(this);
}
_input2.Notify(_input2);
}
}
public override IEnumerable<PinValue> InputValues
{
get
{
var result = new List<PinValue>();
if (Input1 != null)
{
result.Add(Input1.Value);
}
if (Input2 != null)
{
result.Add(Input2.Value);
}
return result.ToArray();
}
}
}
AndGate.cs
public class AndGate : BinaryGate
{
// constructors
public AndGate(bool? input1, bool? input2)
{
Output = new Pin();
Input1 = new Pin(input1);
Input2 = new Pin(input2);
}
public AndGate()
: this(null, null)
{ }
// methods
/// <summary>
/// Not implemented. Don't use.
/// </summary>
public override void OnCompleted()
{
}
public override void OnError(Exception error)
{
throw error;
}
public override void OnNext(Pin value)
{
if (Output != null
&& Input1 != null
&& Input2 != null
&& Output.Value != (Input1.Value && Input2.Value))
{
Output.Value = (Input1.Value && Input2.Value);
}
}
}
The AndGate.cs contains just an example of a logic gate, there are others of course, but the implementation is similar to the AndGate so I'm not putting them here.