C# Public field that can be updated only from within the class - c#

I have a C# class with a field that needs to be visible from outside the class, but should be changed only from within the class. However, the problem is that the field is updated via a public mutator method, not directly (or by a property):
public class FirstClass
{
public SecondClass TheField {get; private set;}
public FirstClass()
{
TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
TheField.Update(/*parameters*/);
// ...
}
}
public class SecondClass
{
// some fields
public SecondClass() { }
public void Update(/*parameters*/)
{
// do something
}
}
In other words, I would like the method Update() to be accessible only from within FirstClass.
Few possible solutions and the reasons why I'm not safisfied with them:
Change SecondClass with a setter instead of a method. - Wouldn't work because I need to have parameters and a lot of stuff to do.
Make Update() internal instead of public. - Still accessible from within the assembly, not good enough.
Modify SecondClass from the FirstClass, ie. move the method Update() to FirstClass, make it private and expose all needed fields from SecondClass. - doesn't feel very object-oriented.
Call Update() from SecondClass constuctor(s) and make a new instance of SecondClass every time I need to update it. - The performance will suffer because there is some stuff in SecondClass that never changes and I would want to process it every time I call Update().
Is there a way to do this?

A basic implementation of #aquaraga's answer, but using interfaces instead:
public interface ISecond
{
// some properties
}
public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : ISecond
{
// some properties
public void Update(/*parameters*/)
{
// do something
}
}
}
Essentially, expose a public interface that has all the accessible members but no Update method. Employ a private nested class which has an Update method, but otherwise not accessible to calling code and expose it as the interface, not as the class.
Some sample usage:
FirstClass myFirst = ...
myFirst.SomeMethod(); //updates ok!
Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
myFirst.TheField.Update(); //compiler error!
One point is that you mention using "some fields"; as an interface you wouldn't be able to have fields but properties instead. I'm not sure if that's a deal breaker or not for you.
EDIT: You mentioned your intent to reuse the SecondClass and minimize code duplication. One quick fix might be to declare some abstract class, a protected Update method, employ an internal constructor (so other assemblies can't inherit from it), then expose the Update call with a minimal implementation:
public abstract class SecondClassBase : ISecond
{
// some properties
internal SecondClassBase()
{
}
protected void Update(/*parameters*/)
{
// do something
}
}
Then in your FirstClass, nothing changes except the nested class:
public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : SecondClassBase
{
public new void Update(/*parameters*/)
{
base.Update(/*parameters*/);
}
}
}
Still some code duplication, but all you need to do now is copy/paste the code; no need to redeclare the properties or the Update logic for each implementation of FirstClass. You could also rename the new Update method to something else to avoid method hiding, but I figured I'd keep the same calling signature you had before.

One way is to make a sub-class called UpdateableSecondClass an inner class to FirstClass.
It would inherit from SecondClass, and have a single method: Update()
Your SecondClass should not have the Update() method at all. You could continue exposing it to the rest of the world:
public SecondClass TheField {get; private set;}

I think that you can use this pattern:
public partial class FirstClass {
partial class ThirdClass: SecondClass {
public void PerformUpdate(/* parameters */) {
base.Update(/* parameters */);
}
}
public void SomeMethod() {
}
public FirstClass() {
}
public SecondClass TheProperty {
get {
return m_TheField;
}
}
ThirdClass m_TheField=new ThirdClass();
}
public partial class SecondClass {
protected void Update(/* parameters */) {
}
public SecondClass() {
}
}
The ThirdClass inherits from SecondClass, but is not exposed. The property exposed as an instance of type SecondClass, but in fact a field of type ThirdClass.
The method SecondClass.Update exposes to derived class only. That you can declare SecondClass public, not nested, but keep the updating of filed private.

What about a Nested Type.
public class FirstClass
{
private SecondClass TheField { get; set; }
public void SomeMethod()
{
TheField.Update( /*parameters*/);
}
private class SecondClass
{
public void Update( /*parameters*/)
{
// do something
}
}
}

Chris Sinclair answer is great,this is just another option
public sealed class FirstClass : SecondClass
{
public FirstClass()
{
}
public void SomeMethod(int j)
{
base.Update(j);
}
}
public abstract class SecondClass
{
public SecondClass() { }
protected void Update(int i)
{
Console.WriteLine(i.ToString());
}
}
this is just for the part of accessing the method through FirstClass

Related

Passing child method to base constructor

I have a base class that implements some logic and eventually calls an Action which was passed to the contructor.
public class BaseClass
{
private Action action;
public BaseClass(Action someAction)
{
action += someAction;
}
private void doStuff()
{
action();
}
}
Now I want to derive some child classes that implement some specific logic. In these child classes I have a method for that logic and my attempt was to pass this method to the base constructor. But this result in a compiler error CS0120: An object reference is required for the nonstatic field, method, or property 'member'.
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
: base(doSpecificStuff) // <-- compiler error CS0120 here
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
I don't quite get why it fails at that point. Is it because the base constructor gets called first which means when calling it I do not have an instance of the child class (including the child's method)?
But why does the compiler asks for a reference to a nonstatic field? Actually I don't see anything static here. Is there a way to get a reference to doSpecificStuff at that point? this.doSpecificStuff does not work, resulting in CS0027: Keyword 'this' is not available in the current context.
Any suggestions for a better design?
This is exactly where object-oriented-design (OOP) and one of its principles, Polymorphism, comes in place, and what it was designed for.
By making doStuff virtual in the base class, we can override the method in the specific class and customize its behavior.
public class BaseClass
{
private Action? action;
public BaseClass(Action someAction)
{
action += someAction;
}
protected BaseClass()
{
}
protected virtual void doStuff()
{
action?.Invoke();
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
{
b = i;
}
protected override void doStuff()
{
// do something depending on b
}
}
I don't quite get why it fails at that point. Is it because the base constructor gets called first which means when calling it I do not have an instance of the child class (including the child's method)?
Sort of. There is actually an instance of the child class (the object is created immediately of the "right" type) but you can't refer to anything specific to the instance in the constructor initializer.
From section 15.11.2 of the draft C# 6 spec:
An instance constructor initializer cannot access the instance being created.
The best way of handling this really depends on the broader context. For example, you could accept a Func<BaseClass, Action> instead and cast:
public class BaseClass
{
private Action action;
public BaseClass(Func<BaseClass, Action> actionProvider)
{
action += actionProvider(this);
}
private void doStuff()
{
action();
}
}
... then:
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
: base(x => ((SpecificClass) x).doSpecificStuff)
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
That's a bit tortuous though. If the action is always expected to be a method in the derived class, an option would be to create an abstract method in the base class and just override it in the derived class instead.
The error message means that the compiler is expecting this:
private static void doSpecificStuff()
{
// do something depending on b
}
Why? because when you call your action in doStuff, C# has no way to now that doSpecificStuff has to be called on the current (this) instance.
To compile, you would have to do something like this :
public class BaseClass
{
private Action action;
public BaseClass(Action<BaseClass> someAction)
{
action += () => someAction(this);
}
private void doStuff()
{
action();
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i): base(x => ((SpecificClass)x).doSpecificStuff()) // <-- compiler error CS0210 here
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
I do not know exactly why you came up with this approach but why not just us inheritance? (Again, there might be some specific need I'm not aware of here, I'm just mentioning this for the record to post an answer as complete as possible) For instance:
public class BaseClass
{
public BaseClass()
{
}
protected virtual void doStuff()
{
// Doing stuff...
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i): base()
{
b = i;
}
protected override void doStuff()
{
// do something depending on b
base.doStuff()// if needed...
}
}

Restrict class from instantiation and encapsulate it in property in another class [duplicate]

This question already has answers here:
Best way to prevent a class from being Instantiated?
(5 answers)
Closed 2 years ago.
Im writing a .net Standard class library and I want to publish it as an internal package,so i have two classes in same project let say as below :
public class classOne
{
public void SomeMethod()
{
}
}
public class classTwo
{
private ClassOne _classOne;
public classOne clsOne
{
get
{
lock (padlock)
{
if (_classOne== null)
_classOne= new ClassOne ();
return _classOne;
}
}
}
}
As you seen above I want the developers to use class one as a property inside classTwo Also I want to prevent the instantiation of classOne. just the only way to call classOne methods is through classTwo "clsOne" property.
//I want this code
classTwo clsTwo = new classTwo();
clsTwo.clsOne.someMethod();
//And Prevent to do this code
classOne clsOnew= new classOne();
clsOne.someMethod();
how do i implement that ?
If you only care about ClassOne not being instantiated outside of your package, you could make the constructor of ClassOne internal.
If you only want ClassOne to be instantiated by ClassTwo, you could make a public interface, IClassOne and make ClassOne implement IClassOne and be a private nested class inside ClassTwo.
public interface IClassOne
{
void SomeMethod();
}
public class ClassTwo
{
private ClassOne _classOne;
public IClassOne clsOne
{
get
{
lock (padlock)
{
if (_classOne== null)
_classOne= new ClassOne ();
return _classOne;
}
}
}
private class ClassOne : IClassOne
{
public void SomeMethod()
{
// do something
}
}
}
I believe you want ClassOne to be static.
It should look something like this.
public static class classOne
{
public static void SomeMethod()
{
// Your logic
}
}
Then in the ClassTwo constructor or where ever you desire that function call,
public class classTwo
{
public classTwo()
{
classOne.SomeMethod();
}
}
I think what you want is a nested class.
public class ClassTwo
{
public class ClassOne
{
// methods
}
// property
}
But how would you prevent instantiation? Perhaps you could try something like this:
public class ClassTwo
{
private class Token
{
public static readonly Token Instance = new Token();
private Token(){}
}
public class ClassOne
{
public ClassOne(Token token){}
// methods
}
// property
}
Because the token class is private within ClassTwo, only ClassTwo can use it to construct ClassOne.
You could modify access to the constructor of ClassOne by making it private.
If I understand your question properly the only purpose of ClassTwo is to allow access to a single instance of ClassOne in which case you can use the standard Singleton C# pattern to achieve this in one class.
public sealed class ClassOne
{
// Make the constructor private
private ClassOne()
{
}
private static ClassOne instance;
private static readonly object _lock = new object();
public static ClassOne Instance
{
get
{
// only get a new reference if one doesn't already exist
if (instance == null)
{
lock (_lock)
{
if (instance == null)
{
instance = new ClassOne();
}
}
}
return instance;
}
}
public void SomeMethod()
{
// Do work
}
}
Since the constructor is private we cannot create instances of ClassOne outside of the class itself.
// Valid
var instance = ClassOne.Instance;
// Invalid
var instance2 = new ClassOne();
instance.SomeMethod();

How to prevent calling constructor of one class while having access to its member functions in C#?

I have a class A, and a class AStore. My requirement is to prevent all other methods from initializing an instance of class A, which they should get an instance from AStore. In addition, I also need to access the member functions of A from the instance.
Factory pattern is not suitable for this problem as the constructor of A is still public. Ideally, it should throw compilation error when calling the constructor of class A while having access to its member functions.
Can I get C# solutions to this?
For restricting others to create an instance of class A you can use a private constructor and a static factory method to get the instance of that class.
public class A
{
private A(){}
public static A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
To enforce instance creation of A only via Astore you can use protected modifier and derive AStore from A. That way, only AStore will have access to its protected members like 'constructor' or 'factory method':
public class Astore : A
{
public A GetInstanceOfA()
{
return base.GetInstance();
}
}
public class A
{
protected A() { }
protected A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
//Usage
public class ConsumerClass
{
public void Test()
{
var a = new A(); // Compile error
a = new Astore().GetInstanceOfA();
a.MemberFunctionOfA();
}
}
But there're still chances that another class say 'UnWantedStore' can derive from A and serve instance of A.
Another approach is moving AStore and A classes to the dedicated project and make constructor of A class internal.
// Project A
namespace ProjectA
{
public class A
{
public int PropertyOne { get; set; }
public string PropertyTwo { get; set; }
internal A() {}
}
public class AStore
{
public A CreateA()
{
//internal constructor can be used
return A();
}
}
}
// Project ConsumerOfA
namespace ConsumerOfA
{
public static void UseA()
{
var store = new AStore();
var instanceOfA = store.CreateA();
// have access to the A's public members
}
}
With this approach you will get perfect encapsulation you trying to achive.
Abstract classes to the rescue!
Indeed, there's yet another possible approach! I've never used it but it might work in your scenario. See the following code sample:
public abstract class A
{
public string Text { get; set; }
public string SayHello() => "hello world!";
}
public class AStore
{
private class AInternal : A {}
public void DoStuff()
{
A a = new AInternal();
a.Text = "whatever";
string helloText = a.SayHello();
}
}
Let's explain the approach:
Class A is abstract, therefore it can't be instantiated.
Class AStore implements a private nested class called AInternal which just inherits A to let AStore members be able to instantiate A. Since AInternal is private, no other class than AStore can instantiate AInternal!
Class AStore can access public A members because AInternal inherits A!
You can do this with reflection too:
public class ClassA
{
// The constructor(s) have to be private
private ClassA() { }
// Whatever other code you want
}
public class ClassB
{
public static ClassA GetClassAInstance()
{
// Use reflection to get the private default constructor
ConstructorInfo constructor = typeof(ClassA).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
ClassA instance = constructor.Invoke(new object[] { }) as ClassA;
return instance;
}
}
You can find more information on the GetConstructor method here.

Is it possible to "inherit" tests with xUnit.net?

I have a concrete class called EventManager and a subclass called ScheduledEventManager. I would like ScheduledEventManager to have to pass the same tests as EventManager plus a few additional ones. Is this possible with xUnit.net?
EDIT: I just realized that my case is a little more complicated than this. I'm using nested classes to keep my tests more organized. Example:
public class EventManagerTests
{
public class WhenAnEventIsFired
{
[Fact]
void ItNotifiesSubscribers()
{
// Perform the test
}
}
}
public class ScheduledEventManagerTests
{
// How to I inherit the above tests since they are in nested classes?
}
It seems to me that this is not possible, but maybe one of you geniuses knows something I don't.
Yes You can:
public abstract class EventManagerTests
{
protected IEventManager _ev;
protected EventManagerTests(IEventManager ev)
{
_ev = ev;
}
[Fact]
public void SharedTest()
{
// Perform _ev test
}
}
public class ScheduledEventManagerTests : EventManagerTests
{
public ScheduledEventManagerTests():base(new ScheduledEventManager())
{
}
// It will inherit tests from the base abstract class
}
public class UnScheduledEventManagerTests : EventManagerTests
{
public UnScheduledEventManagerTests():base(new UnScheduledEventManager())
{
}
// It will inherit tests from the base abstract class
}
Create a parameterized test that takes an instance of your base class as the SUT, and invoke the test with an instance of the sub class. Here's a (contrived) example using NUnit, which results in one passing and one failing test:
public class Foo
{
public virtual int DoSomething()
{
return 10;
}
}
public class Bar : Foo
{
public override int DoSomething()
{
return 9;
}
}
[TestFixture]
public class Tests
{
private Foo[] _foos = { new Foo(), new Bar() };
[Test]
[TestCaseSource("_foos")]
public void When_DoSomething_Is_Invoked_Then_A_Power_Of_Ten_Is_Returned(Foo sut)
{
Assert.That(sut.DoSomething() % 10, Is.EqualTo(0));
}
}

Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

Recently I've been thinking about securing some of my code. I'm curious how one could make sure an object can never be created directly, but only via some method of a factory class. Let us say I have some "business object" class and I want to make sure any instance of this class will have a valid internal state. In order to achieve this I will need to perform some check before creating an object, probably in its constructor. This is all okay until I decide I want to make this check be a part of the business logic. So, how can I arrange for a business object to be creatable only through some method in my business logic class but never directly? The first natural desire to use a good old "friend" keyword of C++ will fall short with C#. So we need other options...
Let's try some example:
public MyBusinessObjectClass
{
public string MyProperty { get; private set; }
public MyBusinessObjectClass (string myProperty)
{
MyProperty = myProperty;
}
}
public MyBusinessLogicClass
{
public MyBusinessObjectClass CreateBusinessObject (string myProperty)
{
// Perform some check on myProperty
if (true /* check is okay */)
return new MyBusinessObjectClass (myProperty);
return null;
}
}
It's all okay until you remember you can still create MyBusinessObjectClass instance directly, without checking the input. I would like to exclude that technical possibility altogether.
So, what does the community think about this?
You can make the constructor private, and the factory a nested type:
public class BusinessObject
{
private BusinessObject(string property)
{
}
public class Factory
{
public static BusinessObject CreateBusinessObject(string property)
{
return new BusinessObject(property);
}
}
}
This works because nested types have access to the private members of their enclosing types. I know it's a bit restrictive, but hopefully it'll help...
Looks like you just want to run some business logic before creating the object - so why dont you just create a static method inside the "BusinessClass" that does all the dirty "myProperty" checking work, and make the constructor private?
public BusinessClass
{
public string MyProperty { get; private set; }
private BusinessClass()
{
}
private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}
public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty
if (/* all ok */)
return new BusinessClass(myProperty);
return null;
}
}
Calling it would be pretty straightforward:
BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);
Or, if you want to go really fancy, invert control: Have the class return the factory, and instrument the factory with a delegate that can create the class.
public class BusinessObject
{
public static BusinessObjectFactory GetFactory()
{
return new BusinessObjectFactory (p => new BusinessObject (p));
}
private BusinessObject(string property)
{
}
}
public class BusinessObjectFactory
{
private Func<string, BusinessObject> _ctorCaller;
public BusinessObjectFactory (Func<string, BusinessObject> ctorCaller)
{
_ctorCaller = ctorCaller;
}
public BusinessObject CreateBusinessObject(string myProperty)
{
if (...)
return _ctorCaller (myProperty);
else
return null;
}
}
:)
You could make the constructor on your MyBusinessObjectClass class internal, and move it and the factory into their own assembly. Now only the factory should be able to construct an instance of the class.
After so many years this got asked, and all the answers I see are unfortunately telling you how you should do your code instead of giving a straight answer. The actual answer you were looking for is having your classes with a private constructor but a public instantiator, meaning that you can only create new instances from other existing instances... that are only available in the factory:
The interface for your classes:
public interface FactoryObject
{
FactoryObject Instantiate();
}
Your class:
public class YourClass : FactoryObject
{
static YourClass()
{
Factory.RegisterType(new YourClass());
}
private YourClass() {}
FactoryObject FactoryObject.Instantiate()
{
return new YourClass();
}
}
And, finally, the factory:
public static class Factory
{
private static List<FactoryObject> knownObjects = new List<FactoryObject>();
public static void RegisterType(FactoryObject obj)
{
knownObjects.Add(obj);
}
public static T Instantiate<T>() where T : FactoryObject
{
var knownObject = knownObjects.Where(x => x.GetType() == typeof(T));
return (T)knownObject.Instantiate();
}
}
Then you can easily modify this code if you need extra parameters for the instantiation or to preprocess the instances you create. And this code will allow you to force the instantiation through the factory as the class constructor is private.
Apart from what Jon suggested, you could also either have the factory method (including the check) be a static method of BusinessObject in the first place. Then, have the constructor private, and everyone else will be forced to use the static method.
public class BusinessObject
{
public static Create (string myProperty)
{
if (...)
return new BusinessObject (myProperty);
else
return null;
}
}
But the real question is - why do you have this requirement? Is it acceptable to move the factory or the factory method into the class?
Yet another (lightweight) option is to make a static factory method in the BusinessObject class and keep the constructor private.
public class BusinessObject
{
public static BusinessObject NewBusinessObject(string property)
{
return new BusinessObject();
}
private BusinessObject()
{
}
}
So, it looks like what I want cannot be done in a "pure" way. It's always some kind of "call back" to the logic class.
Maybe I could do it in a simple way, just make a contructor method in the object class first call the logic class to check the input?
public MyBusinessObjectClass
{
public string MyProperty { get; private set; }
private MyBusinessObjectClass (string myProperty)
{
MyProperty = myProperty;
}
pubilc static MyBusinessObjectClass CreateInstance (string myProperty)
{
if (MyBusinessLogicClass.ValidateBusinessObject (myProperty)) return new MyBusinessObjectClass (myProperty);
return null;
}
}
public MyBusinessLogicClass
{
public static bool ValidateBusinessObject (string myProperty)
{
// Perform some check on myProperty
return CheckResult;
}
}
This way, the business object is not creatable directly and the public check method in business logic will do no harm either.
In a case of good separation between interfaces and implementations the
protected-constructor-public-initializer pattern allows a very neat solution.
Given a business object:
public interface IBusinessObject { }
class BusinessObject : IBusinessObject
{
public static IBusinessObject New()
{
return new BusinessObject();
}
protected BusinessObject()
{ ... }
}
and a business factory:
public interface IBusinessFactory { }
class BusinessFactory : IBusinessFactory
{
public static IBusinessFactory New()
{
return new BusinessFactory();
}
protected BusinessFactory()
{ ... }
}
the following change to BusinessObject.New() initializer gives the solution:
class BusinessObject : IBusinessObject
{
public static IBusinessObject New(BusinessFactory factory)
{ ... }
...
}
Here a reference to concrete business factory is needed to call the BusinessObject.New() initializer. But the only one who has the required reference is business factory itself.
We got what we wanted: the only one who can create BusinessObject is BusinessFactory.
public class HandlerFactory: Handler
{
public IHandler GetHandler()
{
return base.CreateMe();
}
}
public interface IHandler
{
void DoWork();
}
public class Handler : IHandler
{
public void DoWork()
{
Console.WriteLine("hander doing work");
}
protected IHandler CreateMe()
{
return new Handler();
}
protected Handler(){}
}
public static void Main(string[] args)
{
// Handler handler = new Handler(); - this will error out!
var factory = new HandlerFactory();
var handler = factory.GetHandler();
handler.DoWork(); // this works!
}
I don't understand why you want to separate the "business logic" from the "business object". This sounds like a distortion of object orientation, and you'll end up tying yourself in knots by taking that approach.
I'd put the factory in the same assembly as the domain class, and mark the domain class's constructor internal. This way any class in your domain may be able to create an instance, but you trust yourself not to, right? Anyone writing code outside of the domain layer will have to use your factory.
public class Person
{
internal Person()
{
}
}
public class PersonFactory
{
public Person Create()
{
return new Person();
}
}
However, I must question your approach :-)
I think that if you want your Person class to be valid upon creation you must put the code in the constructor.
public class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
Validate();
}
}
This solution is based off munificents idea of using a token in the constructor. Done in this answer make sure object only created by factory (C#)
public class BusinessObject
{
public BusinessObject(object instantiator)
{
if (instantiator.GetType() != typeof(Factory))
throw new ArgumentException("Instantiator class must be Factory");
}
}
public class Factory
{
public BusinessObject CreateBusinessObject()
{
return new BusinessObject(this);
}
}
Multiple approaches with different tradeoffs have been mentioned.
Nesting the factory class in the privately constructed class only allows the factory to construct 1 class. At that point you're better off with a Create method and a private ctor.
Using inheritance and a protected ctor has the same issue.
I'd like to propose the factory as a partial class that contains private nested classes with public constructors. You're 100% hiding the object your factory is constructing and only exposing what you choose to through one or multiple interfaces.
The use case I heard for this would be when you want to track 100% of instances in the factory. This design guarantees no one but the factory has access to creating instances of "chemicals" defined in the "factory" and it removes the need for a separate assembly to achieve that.
== ChemicalFactory.cs ==
partial class ChemicalFactory {
private ChemicalFactory() {}
public interface IChemical {
int AtomicNumber { get; }
}
public static IChemical CreateOxygen() {
return new Oxygen();
}
}
== Oxygen.cs ==
partial class ChemicalFactory {
private class Oxygen : IChemical {
public Oxygen() {
AtomicNumber = 8;
}
public int AtomicNumber { get; }
}
}
== Program.cs ==
class Program {
static void Main(string[] args) {
var ox = ChemicalFactory.CreateOxygen();
Console.WriteLine(ox.AtomicNumber);
}
}
I don't think there is a solution that's not worse than the problem , all he above require a public static factory which IMHO is a worse problem and wont stop people just calling the factory to use your object - it doesnt hide anything . Best to expose an interface and/or keep the constructor as internal if you can that's the best protection since the assembly is trusted code.
One option is to have a static constructor which registers a factory somewhere with something like an IOC container.
Here is another solution in the vein of "just because you can doesn't mean you should" ...
It does meet the requirements of keeping the business object constructor private and putting the factory logic in another class. After that it gets a bit sketchy.
The factory class has a static method for creating business objects. It derives from the business object class in order to access a static protected construction method that invokes the private constructor.
The factory is abstract so you can't actually create an instance of it (because it would also be a business object, so that would be weird), and it has a private constructor so client code can't derive from it.
What's not prevented is client code also deriving from the business object class and calling the protected (but unvalidated) static construction method. Or worse, calling the protected default constructor we had to add to get the factory class to compile in the first place. (Which incidentally is likely to be a problem with any pattern that separates the factory class from the business object class.)
I'm not trying to suggest anyone in their right mind should do something like this, but it was an interesting exercise. FWIW, my preferred solution would be to use an internal constructor and the assembly boundary as the guard.
using System;
public class MyBusinessObjectClass
{
public string MyProperty { get; private set; }
private MyBusinessObjectClass(string myProperty)
{
MyProperty = myProperty;
}
// Need accesible default constructor, or else MyBusinessObjectFactory declaration will generate:
// error CS0122: 'MyBusinessObjectClass.MyBusinessObjectClass(string)' is inaccessible due to its protection level
protected MyBusinessObjectClass()
{
}
protected static MyBusinessObjectClass Construct(string myProperty)
{
return new MyBusinessObjectClass(myProperty);
}
}
public abstract class MyBusinessObjectFactory : MyBusinessObjectClass
{
public static MyBusinessObjectClass CreateBusinessObject(string myProperty)
{
// Perform some check on myProperty
if (true /* check is okay */)
return Construct(myProperty);
return null;
}
private MyBusinessObjectFactory()
{
}
}
Would appreciate hearing some thoughts on this solution.
The only one able to create 'MyClassPrivilegeKey' is the factory. and 'MyClass' requires it in the constructor.
Thus avoiding reflection on private contractors / "registration" to the factory.
public static class Runnable
{
public static void Run()
{
MyClass myClass = MyClassPrivilegeKey.MyClassFactory.GetInstance();
}
}
public abstract class MyClass
{
public MyClass(MyClassPrivilegeKey key) { }
}
public class MyClassA : MyClass
{
public MyClassA(MyClassPrivilegeKey key) : base(key) { }
}
public class MyClassB : MyClass
{
public MyClassB(MyClassPrivilegeKey key) : base(key) { }
}
public class MyClassPrivilegeKey
{
private MyClassPrivilegeKey()
{
}
public static class MyClassFactory
{
private static MyClassPrivilegeKey key = new MyClassPrivilegeKey();
public static MyClass GetInstance()
{
if (/* some things == */true)
{
return new MyClassA(key);
}
else
{
return new MyClassB(key);
}
}
}
}

Categories

Resources