Let's say I have a Manager class
public class Manager {
public Item Create() {
...
return new Item(...);
}
}
and I have an Item class:
public class Item {
[AllowCallBy(typeof(Manager))]
public Item(...) {
}
...
}
Now, I would like to use the easiest and most straightforward way to analyze the attributes like AllowCallBy at compile time and display errors or warnings. If, in this particular case, a class other than Manager class tries to instantiate Item with new Item(...) I would like to display something like "don't instantiate Item class directly, call Manager.Create(...) instead".
I suppose that at least one of the systems: Roslyn, ReSharper, PostSharp or maybe something else would allow me to do it or something that is very close to what I'm trying to achieve. Could somebody give an example of what to use and how to use it?
This is definitely a code smell as #Habib mentions (can someone link to a specific one?), but without a more complete example it's difficult to offer alternatives beyond what has already been suggested in comments. I'd encourage you to expand your sample or rethink your design.
However, I can present one option that I've used in the past though not for this purpose. You could mark Item's constructor as Obsolete:
public class Item {
[Obsolete("Don't instantiate Item class directly, call Manager.Create(...) instead")]
public Item(...) {
}
...
}
Then in your Manager class, you'd specifically ignore this warning where you invoke the constructor:
public class Manager {
public Item Create() {
...
#pragma warning disable 618
return new Item(...);
#pragma warning restore 618
}
}
This way, whenever someone tries to create their own Item elsewhere in the code, they'll get a level 2 CS0618 warning indicating that they should not use the method (note that I didn't say cannot) with exactly the text entered in the attribute. If warnings as errors is enabled (for all warnings or just this one), then it will be a compile error as you originally wanted.
Be aware, nothing prevents others from adding these pragma statements to get around the error. However, with this method the developer can't say they didn't know they weren't supposed to use the constructor.
Well color me surprised. PostSharp lets you do exactly what you're looking for. In a nutshell, you'd use the ComponentInternalAttribute to control visibility of a type:
public class Item {
[ComponentInternal(typeof(Manager))]
public Item(...) {
}
...
}
According to their documentation linked above, attempting to invoke Item's constructor outside of Manager will yield a compile-time warning:
Method Item.ctor cannot be referenced from [some other method] because of the [ComponentInternal] constraint.
You can make it an error by changing the severity level of the attribute:
public class Item {
[ComponentInternal(typeof(Manager), Severity = SeverityType.Error)]
public Item(...) {
}
...
}
There are way better ways to achieve your goal than your current approach, given that you can actually change that code.
You could for example mark the contructor of Item class as private and add a static factory method to Item class which would be responsible for creating an instance of the class.
Another way is to move Item class to another assembly, mark its constructor as internal and implement another class (a factory) which would be responsible for creating different Item objects. Then you class is visible from other assemblies, but it cannot be directly instantiated, so forces the code user to use provided factory.
Related
I want to store multiple objects in the database. The type of objects are not fixed and can be dynamically added by loaded modules. At one part in my application I want to search for the correct implementation to invoke the method with the created object.
One example. I have 3 objects:
public class Employee : Person { }
public class Supervisor : Person { }
public abstract class Person { }
and there are implementations of IExporter registered at the DI container:
public interface IExporter<T> where T: Person
{
Task ExportAsync(T person);
}
public class EmployeeExporter : IExporter<Employee>
{
public Task ExportAsync(Employee exployee) => Task.CompletedTask; // TODO
}
public class SupervisorExporter : IExporter<Supervisor>
{
public Task ExportAsync(Supervisor supervisor) => Task.CompletedTask; // TODO
}
How would my person factory which returns a person would know which Exporter is the right one to choose for export?
var type = typeof(IExporter<>).MakeGenericType(person.GetType());
var exporter = (IExporter<Employee>)serviceProvider.GetRequiredService(type);
await exporter.ExportAsync(person);
Something like this but without explicitly specify the IExporter<Employee> cast.
Or do I something completely wrong?
I already mentioned Jimmy Bogard's article, so I won't repeat that. Besides the options mentioned by Jimmy, there's another option, which is to use C# dynamic. This looks like this:
var type = typeof(IExporter<>).MakeGenericType(person.GetType());
dynamic exporter = serviceProvider.GetRequiredService(type);
await exporter.ExportAsync((dynamic)person);
At runtime, the C# compiler goes look for a method called ExportAsync. This is about the most concise solution you can get. But be aware of the following downsides:
Refactoring: This is not refactoring safe. If you refactor the IExporter<T> interface, this code keeps compiling but fails at runtime. You should add a unit test for your factory to make sure it still works.
Public only: Using the dynamic keyword, you can only invoke public methods on public classes. Even if your IExporter<T> is defined as public, when the exporter implementation (or the outer-most decorator your decided to wrap it with) is internal, the invocation will fail. To me this seems like a quirk in the C# compiler, because IMO it should be able to call ExportAsync when its interface is public, but that's not how it works. So again, you might want to add some unit tests to make sure it works.
What it comes down to when using dynamic, is that you'll be adding more tests than with the approaches Jimmy suggests. His solutions have more code and need less testing. Dynamic needs no extra code, but more testing code.
I made a program that works just fine as-is, however i want to organize code better by moving some of my logic into other .cs files; upon moving some code i noticed that code reffering the "this" keyword for changing the applications width / height no longer function and ive had no luck trying to get a handle to "this", please help
int heightd = (int)this.Height;
Edit: To further clarify. My mainwindow.xaml.cs is where all my code was before.
I would use this.width to get my windows width.
Upon creating a different .cs file to hold related methods, it broke all of my "this" refferences.
I want for my NEW cs file to be able to get a handle on "this" from my main program. so i can call its width, height, etc
Re-edit: I understand that "this" is not going to function properly from my new class I just want to be able to create methods that use the same object that is accessed when "this" is refferenced.
So for example, Class2 can do WorkAround.height ; where WorkAround is a handle to whatever "this" is in class 1.
Soution: updated signature in new class to accept the main window:
public static void Marginnn(MainWindow aplication)
{
send "this" from main class during the call:
WindowsInterop.Marginnn(this);
Others have discussed partial classes, which can be problematic. For this answer, I assume by "move to another .cs file" you mean "move to another class," as your title indicates.
The this keyword is effectively a variable that refers to the instance that "owns" the current method. If the method is moved to another type, then the instance can no longer be the owner of the method. Instead, you need to pass a reference to the instance into the method instead. That will be a method parameter, which will have a name other than this.
Example; before:
class App
{
public void DoSomethingWithTheHeight()
{
int heightd = (int)this.Height;
//more code
}
public void CallDoSomethingWithTheHeight()
{
this.DoSomethingWithTheHeight();
}
}
Task: move DoSomethingWithTheHeight to a new static class:
class App
{
public void CallDoSomethingWithTheHeight()
{
NewClass.DoSomethingWithTheHeight(this);
}
}
static class NewClass
{
public static void DoSomethingWithTheHeight(App application)
{
int heightd = (int)application.Height;
//more code
}
}
Task: move DoSomethingWithTheHeight to a new non-static class:
class App
{
public void CallDoSomethingWithTheHeight()
{
NewClass instanceOfNewClass = new NewClass();
instanceOfNewClass.DoSomethingWithTheHeight(this);
}
}
class NewClass
{
public void DoSomethingWithTheHeight(App application)
{
int heightd = (int)application.Height;
//more code
}
}
There are other possibilities, but these examples should illustrate the basic principle.
If you only want to move part of your class to another file and still use this, you have to use a partial class. But I won't recommend this approach, your code clearly needs some refactoring.
C# keyword this refers to the current instance of the class it's being used in. It can be used for a few other things such as a modifier of the first parameter of an extension method, but we won't worry about that here. So, you may only use this from within the class that it's referring to and note that it may not be used with static classes, methods, fields, etc... since they have no instance associated with them.
If the code you're referring to is not implemented within a partial class, then it has to refer to the instance of the Window. Otherwise, it's impossible to tell what this is. Since we don't know how exactly you're structuring your program, it's hard to recommend a method of fetching the instance of the Window in question. If, for example, you would use the MVVM pattern, you wouldn't even need to interact with the instance of the UI from within the code. However, if you're working with a code-behind model, then your best bet is probably to create a partial class for that window. Like I said, it's hard to know what's right in your situation without knowing the entire scope of your environment.
There are lots of ways to tackle this and some are more hackish than others:
// In the code-behind of a window...
public static MyWindow Instance { get; private set; }
public MyWindow()
{
Initialize();
Instance = this;
}
// Somewhere else in your program...
var someValue = MyWindow.Instance.SomeControl.Value;
Note that the above code is just for demonstration purposes and not something I would recommend doing (it doesn't even account for null, but that's easy to fix). It's simply a demonstration showing that there are almost countless ways of tackling your problem. Ideally, if you're not going with MVVM, I would probably implement a window manager class that handles instances of all of your application windows.
I've got a couple of classes that form a too-complicated object graph. Here's a peek at a smaller scenario. Assume INotifyPropertyChanged is in place.
class A
{
public InternalType InterestingProperty { get; set; }
}
class B
{
public A Component { get; set; }
}
My helper class watches for these events and updates its properties when the properties of the objects change. It does this so some other class that's interested in about a dozen properties on as many objects are easily accessible. This is all packed in a framework that has several variants, so inheritance is in play.
I've finished the first scenario, and ended up with a concrete class like this:
class ScenarioOnePropertySpy
{
protected ScenarioOne PropertySpy(Foo thingToMonitor)
{
_thingToMonitor = thingToMonitor;
RegisterForEvents()
}
public B InterestingB { get; }
protected RegisterForEvents()
{
// * Register for _thingToMonitor propertyChanged if first time.
// * If B is different, unregister the old and register the new.
// * If B hasn't been set yet register for PropertyChanged on it.
// * If B.Component isn't the same as last time unregister the
// old and register the new.
}
protected Update()
{
// Some monitored object changed; refresh property values and
// update events in case some monitored object was replaced.
B = _thingToMonitor.B;
RegisterForEvents()
}
private Handle_PropertyChanged(...) { Update(); }
}
It's icky event registration, but moving that ugliness out of the class that wants to know about the properties is the purpose. Now I've moved on to scenario 2 that monitors different objects/properties and used my concrete class as a guide for an abstract one:
abstract class PropertySpy
{
protected PropertySpy(FooBase thingToMonitor)
{
_thingToMonitor = thingToMonitor;
RegisterForEvents()
}
protected abstract void RegisterForEvents()
// ...
}
Whoops. I've got a virtual method call in the constructor. In theory it's safe for all of my scenarios, but the R# warning keeps digging at me. I'm sure if I move forward one day it's going to cause a problem that'll take a while to figure out. That method's definitely going to need to work with properties on the derived types.
I could drop the method and force derived types to do the event management themselves. That'd defeat the purpose for the base class. And someone would forget to follow the contract and it'd turn into a support incident; I spend enough time writing documentation as it is. Another one I thought of was making RegisterForEvents() publich and requiring users to call it after construction. That "create then initialize" pattern stinks in .NET and people always forget. Currently I'm toying with the notion of another class that does the event registration that's injected via the constructor. Then derived classes can provide that class to achieve the same effect as a virtual method without the dangers. But the thing doing the registration would need practically the same property interface as PropertySpy; it seems tedious but I guess "ugly and works" is better than what I've got.
Anything I'm missing? I'll even take "it's a warning, not a rule" as an answer if the argument is convincing.
Your scenario seems complicated enough to consider a completely different approach to class instantiation. What about using a factory to construct property spies?
public class PropertySpyFactory<T> where T : PropertySpy, new()
{
public static T Create()
{
T result = new T();
// … whatever initialization needs to be done goes here …
result.RegisterForEvents();
return result;
}
}
ScenarioOnePropertySpy spy = PropertySpyFactory<ScenarioOnePropertySpy>.Create();
It's salvagable in the code, instance initialization can be extended easily, and once you turn to an IoC it will feel quite natural and not much refactoring will be needed.
UPDATE: One another option in case a) your spy hierarchy is flat enough and b) you don't need to use a common ancestor or you can substitute it with an interface:
public abstract class PropertySpy<T> where T : PropertySpy, new()
{
public static T Create()
{
T result = new T();
// … whatever initialization needs to be done goes here …
result.RegisterForEvents();
return result;
}
…
}
public class ScenarioOnePropertySpy : PropertySpy<ScenarioOnePropertySpy>
{
…
}
ScenarioOnePropertySpy spy = ScenarioOnePropertySpy.Create();
In other words, the factory method is located right within the common ancestor. The drawback of this approach is that it isn't that orthogonal (the factory isn't separated from the classes being constructed) and hence less extensible and flexible. However, in certain cases may be a valid option.
Last but not least, you can create a factory method in each class again. The advantage is you can keep constructors protected and hence force users to use factory methods instead of direct instantiation.
The key issue I believe is that by the time the virtual method is called, your subclass constructor and initializers have not executed yet. So, in your overridden method, your subclass may not have all the things you expect to be initialized initialized.
I have a class with various public properties which I allow users to edit through a property grid. For persistence this class is also serialized/deserialized to/from an XML file through DataContractSerializer.
Sometimes I want to user to be able to save (serialize) changes they've made to an instance of the class. Yet at other times I don't want to allow the user to save their changes, and should instead see all the properties in the property grid as read only. I don't want to allow users to make changes that they'll never be able to save later. Similar to how MS Word will allow users to open documents that are currently opened by someone else but only as read only.
My class has a boolean property that determines if the class should be read-only, but is it possible to use this property to somehow dynamically add a read-only attributes to the class properties at run-time? If not what is an alternative solution? Should I wrap my class in a read-only wrapper class?
Immutability is an area where C# still has room to improve. While creating simple immutable types with readonly properties is possible, once you need more sophisticated control over when type are mutable you start running into obstacles.
There are three choices that you have, depending on how strongly you need to "enforce" read-only behavior:
Use a read-only flag in your type (like you're doing) and let the caller be responsible for not attempting to change properties on the type - if a write attempt is made, throw an exception.
Create a read-only interface and have your type implement it. This way you can pass the type via that interface to code that should only perform reads.
Create a wrapper class that aggregates your type and only exposes read operations.
The first option is often the easiest, in that it can require less refactoring of existing code, but offers the least opportunity for the author of a type to inform consumers when an instance is immutable versus when it is not. This option also offers the least support from the compiler in detecting inappropriate use - and relegates error detection to runtime.
The second option is convenient, since implementing an interface is possible without much refactoring effort. Unfortunately, callers can still cast to the underlying type and attempt to write against it. Often, this option is combined with a read-only flag to ensure the immutability is not violated.
The third option is the strongest, as far as enforcement goes, but it can result in duplication of code and is more of a refactoring effort. Often, it's useful to combine option 2 and 3, to make the relationship between the read-only wrapper and the mutable type polymorphic.
Personally, I tend to prefer the third option when writing new code where I expect to need to enforce immutability. I like the fact that it's impossible to "cast-away" the immutable wrapper, and it often allows you to avoid writing messy if-read-only-throw-exception checks into every setter.
If you are creating a library, it is possible to define a public interface with a private/internal class. Any method which needs to return an instance of your read-only class to an external consumer should instead return an instance of the read-only interface instead. Now, down-casting to a concrete type is impossible since the type isn't publicly exposed.
Utility Library
public interface IReadOnlyClass
{
string SomeProperty { get; }
int Foo();
}
public interface IMutableClass
{
string SomeProperty { set; }
void Foo( int arg );
}
Your Library
internal MyReadOnlyClass : IReadOnlyClass, IMutableClass
{
public string SomeProperty { get; set; }
public int Foo()
{
return 4; // chosen by fair dice roll
// guaranteed to be random
}
public void Foo( int arg )
{
this.SomeProperty = arg.ToString();
}
}
public SomeClass
{
private MyThing = new MyReadOnlyClass();
public IReadOnlyClass GetThing
{
get
{
return MyThing as IReadOnlyClass;
}
}
public IMutableClass GetATotallyDifferentThing
{
get
{
return MyThing as IMutableClass
}
}
}
Now, anyone who uses SomeClass will get back what looks like two different objects. Of course, they could use reflection to see the underlying types, which would tell them that this is really the same object with the same type. But the definition of that type is private in an external library. At this point, it is still technically possible to get at the definition, but it requires Heavy Wizardry to pull off.
Depending on your project, you could combine the above libraries into one. There is nothing preventing that; just don't include the above code in whatever DLL you want to restrict the permissions of.
Credit to XKCD for the comments.
Why not something like:
private int someValue;
public int SomeValue
{
get
{
return someValue;
}
set
{
if(ReadOnly)
throw new InvalidOperationException("Object is readonly");
someValue= value;
}
I would use a wrapper class that keeps everything read-only. This is for scalability, reliability and general readability.
I do not foresee any other methods of doing this that will provide the above three mentioned benefits as well as something more. Definitely use a wrapper class here in my opinion.
You can not get compile-time checks (like given with the keyword readonly) by changing a property to readonly at runtime. So there is no other way, as to check manually and throw an exception.
But propably it is better to re-design access to the class. For example create a "writer class", which checks if the underling "data class" can currently be written or not.
You can use PostSharp to create OnFieldAccessAspect that will not pass new value to any field when _readOnly will be set to true. With aspect code repetition is gone and there will be no field forgotten.
Would something like this help:
class Class1
{
private bool _isReadOnly;
private int _property1;
public int Property1
{
get
{
return _property1;
}
set
{
if (_isReadOnly)
throw new Exception("At the moment this is ready only property.");
_property1 = value;
}
}
}
You need to catch exceptions when setting properties.
I hope this is something you are looking for.
According to a book I'm reading, the AllowMultiple public property of AttributeUsage specifies:
...whether the target can have multiple instances of the attribute applied to it.
Why would I want/not want to use this?
Attributes are meta-data. Typically, you'll want to decorate a member or type with an Attribute in order to track some information about it.
For example, the DescriptionAttribute is used by the PropertyGrid to label a description of a property:
[Description("This is my property")]
public int MyProperty { get; set; }
Most of the time, having more than one description would not make sense.
However, it is possible that a specific attribute makes sense to use more than once. In that case, you'd want to set the Attribute to allow multiple instances of itself tagged to the same attribute.
(Not that I'd do this, but...) Say you made a custom attribute to track major changes to a class. You might want to list this for every major change:
[Changes(Version=1.1, Change="Added Foo Feature")]
[Changes(Version=2.0, Change="Added Bar Feature")]
public class MyClass
{
// ...
This example might be a little contrived but hopefully it gets the point across.
[Convertable(typeof(Int32)), Convertable(typeof(Double))]
public class Test
{
}
This depends what the attributes are.
For example, you could make an attribute that marks a class as depending on something, and you could allow multiple dependencies.
For a concrete example, look at SuppressMessage, which suppresses a code analysis warning. A member can have multiple warnings that you might want to suppress.
Another example is WebResource; an assembly can contain multiple resources.
No contrived example here, I used it in real production code. I wrote some code to parse a file containing pairs of data like (code=value). I put a custom attribute on a function to indicate it should be called for a given code.
[CanParseCode("G1")]
[CanParseCode("G2")]
private void ParseGXCodes(string code, string value)
{
...
}
This particular format is a somewhat old and domain specific with hundreds of different codes. My goal was to write a framework to make it easier to write file processors that could extract only the codes it needs and ignore the rest. Allowing the same attribute multiple times made it easy to express the intent of the code by simply declaring attributes on the function(s) that process each code.
Real World Application of Attribute AllowMultiple=true usefulness
[ManagesType(typeof(SPEC_SEC_OC), true)]
[ManagesType(typeof(SPEC_SEC_04_OC), true)]
public class LibSpecSelectionView : CustomView
{
public LibSpecSelectionView(SPEC_SEC_OC)
{}
public LibSpecSelectionView(SPEC_SEC_O4_OC)
{}
....
}
public static class ViewManager
{
... static Dictionary of views built via reflection
public void LaunchView(this CollectionBaseClass cbc)
{
... Find class registered to handle cbc type in dictionary and call ctor
}
}
SPEC_SEC_OC myOC = DataClient.Instance.GetSPEC_SEC_OC();
myOC.LaunchView()
I flipped AllowMultiple=true earlier today to allow for the ManagesType attribute to be used more than once. We have several hundred Custom Collection Classes. Most of these custom collections have a view that inherits from CustomView designed to handle creation of a UI view for a specific type of custom collection and presenting it to the user. The ManagesType attribute is used via reflection to build a dictionary of EVERY View in our app that inherits from CustomView to "register" what object type it was designed to handle. The LibSpecSelectionView "broke that pattern" by displaying two different collections at the same time (creates two tabs and shows one custom collection in one tab and the other in the second tab) So the same view is capable of handling two different custom collections.
The dictionary of which views are capable of handling which collection types is then leveraged through an extension method to allow any of our custom collections to launch the registered view (or a default one if there is not a "registered" view) through a one line call to the view manager.