I'm writing a DLL using C# 4.0 which will be used by several C# .NET based desktop applications (let's call them AppA and AppB). It is required that AppA will be able to use certain class' selected fields/properties/functions that won't be even available to AppB. My approach was to use internal modifier for those properties and grant access to AppA by specifying AppA's assembly name in InternalsVisibleTo attribute of the DLL. But internal modifier is also required in some properties which will be accessed in other parts of the DLL but not to be accessed by AppA. Now it appears that there are too many internals which are exposed to AppA which shouldn't be accessible by AppA.
In other words, consider the following properties:
class A
{
internal int ReallyInternal {get; set;}
internal int AppAInternal {get; set;}
}
If I use InternalsVisibleTo attribute for AppA, then both ReallyInternal and AppAInternal properties will be exposed to AppA - where as ReallyInternal shouldn't be exposed to AppA.
How to solve this? Is there any other way to implement this scenario?
Background
Before going to InternalsVisibleTo approach we thought of other ways, like having different interfaces etc. The class library I'm writing will be used by multiple applications. I wanted to have the interface same across applications.
Consider TT4 as a class in the DLL. It's properties will be populated from a physical device via serial communication.
TT4 tt4 = new TT4();
// Some code to populate tt4 object
MessageBox.Show(tt4.SerialNumber);
tt4.SerialNumber = "123";
Because tt4 object will represent a physical device, not all of its properties should be modifiable by all applications. This won't make sense and if we allow this then any application can change the serial number of the device. (Yes, SerialNumber can be written back to the device).
We've only one application (here AppA for example) which will be able to set and change the SerialNumber. Other applications shouldn't do that. It's prevented by making SerialNumber's setter as internal and granting permission to AppA by InternalsVisibleTo.
Please note that providing the library with two classes is not the solution. Say, I've implemented two classes for TT4 - TT4 (cannot write SerialNumber) and TT4Super (can write SerialNumber). When the DLL will be given to clients, they can still see TT4Super and use that.
I'm not the developer of other applications and I have no control of them.
One way to do that would be to extract all the members that should be exposed to AppA to an abstract class (or a parent class in general) and make them protected internal. To access them from AppA it would have to inherit from the abstract class. For instance
public abstract class ParentA
{
internal int ReallyInternal {get; set;}
protected internal int AppAInternal {get; set;}
}
And AppA accesses it the following way:
internal class AinAppA : ParentA
{
internal AinAppA()
{
this.AppAInternal = 1; // can access parents protected members
// this.ReallyInternal = 2; // but pure internal members are not visible
}
}
As a side note, InternalsVisibleTo is not meant to be an access modifier. It's main purpose is to make unit testing easier not to enable communication between production assemblies.
Are you mostly concerned that the designers of AppB are going to do something malicious with your DLL, or that you simply want to prevent them from doing something inadvertently? Making your members internal won't really prevent someone from doing harm via reflection if they want to.
One (admittedly not great) approach you could use is to make these members public, but prevent anyone except AppA from using them, by checking the calling assembly:
private void VerifyCaller(Assembly a)
{
if (a == Assembly.GetExecutingAssembly()) { return; }
var name = a.GetName();
if(name.Name == "AppA" && name.GetPublicKey() == appAPublicKey) { return; }
throw new InvalidOperationException("You can't access this");
}
private string _serialNumber;
public string SerialNumber
{
get { return _serialNumber; }
set
{
VerifyCaller(Assembly.GetCallingAssembly());
_serialNumber = value;
}
}
this should at least prevent anyone from easily using reflection to circumvent your defenses.
Related
I am making a gallery tool that lets you browse and edit objects. I have a 'Library' class that manages the fetching and displaying of the gallery list. I also have an 'ActiveItem' asset that loads all the information of the selected object and deals with modifying it.
Now, there's some information that is stored in the 'library' class (for example the filepath) that I want to use in my activeitem.
I'm a bit confused as to how I can set this up efficiently.
I thought about embedding the activeitem class in the library class, but it gets a bit annoying to have to access all functions and properties of the activeitem through the library class (so instead of writing activeitem.Load() I would have to write lib.activeitem.Load() ). Activeitem already goes 4 levels deep and it's getting a bit much.
Are there other ways of setting this up? Can I store a reference of the library class instance inside the activeitem class, so that the activeitem class can fetch a property of the library instance?
Edit: added some code snippets
This are the class definitions:
class Library
{
...
public string LibDirectory;
...
}
class ActiveAsset
{
...
public SaveAsset()
{
//this method needs to know the LibDirectory property of the libraryclass
}
}
On initiating my winform, I initiate both classes:
Library lib = new Library();
ActiveAsset activeAsset = new ActiveAsset();
Given the concerns in the question comments, if you want ActiveAsset to be able to read information from Library you could change ActiveAsset's constructor to take in Library and store it internally as a private var.
class ActiveAsset
{
private Library _lib
public ActiveAsset(Library lib) {
this._lib = lib
}
public SaveAsset()
{
// reach lib instance from here
this._lib.LibDirectory
//this method needs to know the LibDirectory property of the libraryclass
}
}
If you are worried about design and coupling you could make in interface for Library and then make the constructor use that instead of the Library class
interface ILibrary {
string LibDir { get; set; }
}
class Library : ILibrary {
}
class ActiveAsset
{
private ILibrary _lib
public ActiveAsset(Library lib) {
this._lib = lib
}
public SaveAsset()
{
// reach lib instance from here
this._lib.LibDirectory
//this method needs to know the LibDirectory property of the libraryclass
}
}
As for performance and creating deep levels of nested classes I don't think you will have to worry so much about it, chances are you will hit data save/retrieve performance issues before anything like too many classes. That kind of performance design is only really important when you try to make you code work on small platforms where memory is limited like rasberryPi and such.
I would suggest creating a wrapper class which holds both the Library and the ActiveItem instances. Thus you can have more generalised methods like:
GetAllItems() - gets all items from the library
ActivateItem(Item item) - activates the item provided (stores the given item to a variable in the wrapper class)
etc. Think of that wrapper class as the manager of your application. You would only like to work with that manager regardless of what's beneath it.
Suppose I have a CarSystem class, which has a collection of CarParts objects in it. Now I wish to write a stereo plugin to the system, and I wish the format of all plugins to be:
public interface ICarPluginMetaData
{
string Name {get;}
string Description {get;}
int Status {get; set;}
}
public interface ICarPlugin
{
void int setStatus(int newStatus);
}
[Export(typeof(ICarPlugin))]
[ExportMetaData("Name", "Stereo")]
[ExportMetaData("Description","Plays music")]
[ExportMetaData("Status", 0)]
public class StereoPlugin : ICarPlugin
{
[ICarPluginImport("FrontSpeakers")]
public CarPart myFrontSpeakersPointer;
[ICarPluginImport("RearSpeakers")]
public CarPart myRearSpeakersPointer;
[ICarPluginImport("subwoofer")]
public CarPart mysubwooferPointer;
[Export]
public void setStatus(int newStatus)
{
Status = newStatus;
}
}
Now in my CarSystem class, I define exports, however the default behavior is to create 1 static object, and hand it to all those importing it; how would I be able to do the following:
[ExportAsThreadsafe]
public CarPart FrontSpeakers
[ExportAsThreadsafe]
public CarPart RearSpeakers
[ExportAsThreadsafe]
public CarPart Subwoofer
[ExportAsThreadsafe]
public CarPart DashLights
so that when I create a second plugin, running on a separate thread, I get a threadsafe connection to the actual object for all plugins?
One way to provide thread safety in MEF is to perform a separate independent MEF composition in each thread. Everything constructed in that composition is then local to that thread. Any cross-thread access is under your control and you can use normal thread safety techniques.
I'm not clear on whether you want to load multiple stereo plugins and have them available to / bound to one global CarSystem, or if you are simply talking about having multiple CarSystems in different threads, independent of each other. You can do the latter by MEF composing the CarSystem with a particular stereo plugin inside of a thread.
Here's what I've ended up doing (in pseudocode):
Foreach plugin dynamically loaded
{
//Via reflection
Foreach field in the plugin
{
See if the field has an attribute attached
Find the field who's name is the same as it's attribute's name
{
Using some lookup method, find the object in the CarSystem
collection who's name is the same as the attribute name.
create a concurrencyQueue using proxy object
call field.SetValue(pluginObject, new Proxy Object) //Reflection call
}
}
}
I basically said, "screw MEF doing this automatically" and did it myself, using Reflection and custom Attributes. I used MEF to do one way messaging, but for plugin's that needed to alter objects in the CarSystem I used my custom "MEF" style.
I have a winform application made up of two assemblies : a business layer and a front-end layer. Each usercontrol (front-end layer) relates to a class of the business layer, i.e. CustomerUserControl uses the Customer class.
Editable properties, i.e. Customer.Name, have public setters so that their values can be modified through front-end controls.
My question is : is it possible to change the setter accessibility of a property to make it more or less restrictive only for specific classes. In my example, the Customer.Name setter would be internal, that is not accessible by front-end controls but accessible for its corresponding control CustomerUserControl. Or else, the setter would be public but not accessible to controls other than CustomerUserControl.
Is it possible to achieve such customized access rights ?
I would use the internal modifier for the setter. This makes it only accessible inside the assembly. If the CustomerUserControl is in another assembly then you can use the InternalsVisibleToAttribute
[assembly: InternalsVisibleTo("assembly name")]
EDIT: You are right. Here is another possibility:
Declare an interface that would be implemented by controls that are allowed to set names:
public interface ICustomerNameProvider
{
string CustomerName { get; }
}
In Customer add a method:
public void SetName(ICustomerNameProvider customerNameProvider)
{
this.Name = customerNameProvider.CustomerName;
}
The CustomerUserControl would call it like this:
cust.SetName(this);
Of cause this is not absolutely fool proof, but accidentally passing the wrong control would become impossible.
As far as I know, there's no way to apply what you're asking for directly to a property setter, since it doesn't know where the call initiated from. However, you could cobble something together using mutator methods:
public class Customer
{
...
public string Name
{
get;
private set;
}
public void SetName(string callingControlName, string newName)
{
// you'd use TypeOf the same way to pass in callingControlName
if(TypeOf(this).Name + "UserControl" == callingControlName)
this.Name = newName;
}
...
}
Note that this is ridiculously tightly coupled and poor design practice, but it ought to do what you want, provided you strictly adhere to the naming conventions outlined in the question (Customer matches 1:1 with CustomerUserControl). As an aside, I didn't just statically compare callingControlName to "CustomerUserControl" in order to gain a slight improvement in maintainability, in case you wanted to do something like rename the CustomerUserControl class. Also important to note is the fact that this is easily defeasible by calling Customer.SetName("CustomerUserControl","badName"). Hopefully you aren't exposing this to coders who would do things like that, but it is entirely possible.
The real issue here is that your business layer shouldn't be dependent on your presentation layer. Why would you need to restrict set access to a specific UserControl? If you have a genuine need (and I can't think of one) that a business property's set only be accessible from a certain UI class, then some significant redesigning of your application is called for.
You can limit the scope of get or set accessors like this:
//private set accessor - this is what you're looking for
public int SomeProperty { get; private set; }
//private get accessor
public int SomeOtherProperty { private get; set; }
I have a class:
public class MyClass {
private List<string> folderList;
// .... a lot of useful public methods here.....
}
Everything is fine. The list of folders is encapsulated, the class is accessible through public methods. OK. Now I need an "options" form that allows a user to choose folders for MyClass. There is a catch: new Setup class must have access to private folderList field (or I have to provide public methods to get and set the folder list - it's essentially the same). In old good C++ I would use 'friend' feature because nobody but Setup class may access folderList. But there is no 'friend' feature in C# (I'm a newbie in the C# world).
P.S. Actually I just made folderList public, but I feel there is a better solution.
Thanks.
You can use "internal" keyword to make your method available only within your assembly/project and if you want to access your internal methods in other project or assembly then you can use "InternalsVisibleTo" attribute, where you can access your internals only in that assembly for which you define this attribute.
MSDN Internal Keyword
I believe the keyword you're looking for is internal. It is loosely equivilent to C++'s friend.
Internal provides assembly-level visibility.
Paired with Femaref's suggestion of using a Property, and you should have your full solution.
I am not sure if this is what he/she wanted. He/she did not put the requirement that the potential client will be in current assembly... Accordingly, when using friend in c++ (which was never considered a good style) you must know the exact type of the class which will be entitled to access the member. If this class is not part of the program you are writing, you cannot grant access this way.
If you want conditional access to some property or method of an instance of a class, you will need to implement some kind of entitlement mechanism, for example:
public IList<Folder> GetFolderList(Object pClient, IEntitlementService pService) {
if (pService.IsEntitledToAccess(this, pClient) {
return folderList;
} else {
throw new AccessNotGrantedException("...");
}
}
I believe there are built-in utilities in the .Net framwork for that purpose, just go and google (or bing)...
As an exact answer to the question I would suggest the following - create a separate interface IFolderList:
interface IFolderList
{
IList<string> FolderList { get; }
...
}
Well, you can add other required members to interface
In the class MyClass implement this interface explicitly.
As a result, the class Setup can gain access to data through an explicit cast to an interface IFolderList or work only with these interface.
An alternative to making an internal method to be used by your Setup class would be to use the Visitor pattern and add a method that takes a Setup class instance as a parameter, then uses the private folderList to initialize/change Setup state as required. Of course that would require the appropriate public methods on the Setup class, so might not fit your needs.
Making folderList field public is the worst case. Exposing implementation details through public fields or through poorly designed public property (there are no differences for collections between public fields and public property with getter and setter).
With public fields you can't promote a field to be a property when you want to add validation, change notification, put it into an interface or change your collection type from one type to another.
BTW, Jeffrey Richter in annotation to Framework Design Guideline mentioned that "Personally, I always make my fields private. I don't even expose fields as internal, because doing so would give me no protection from code in my own assembly"
I think the best way to add explicit interface that expose strict abstraction to MyClass clients.
For example, you may add two separate methods to retrieving folders and to adding new folder to this storage:
class MyClass {
//You should return IList<string>
public IList<string> MyList {get {return myList;} }
//Or even IEnumerable<string>, because you should return
//as minimal interface as your clients needs
public IEnumerable<string> MyList {get {return myList;} }
//You may expose this functionality through internal
//method, or through protected internal method,
//but you should avoid direct access to your implementation
//even for descendants or another classes in your assembly
public void AddElement(string s) {myList.Add(s);}
private List<string> myList;
}
That's what properties are for in C#:
public class MyClass
{
private List folderList;
public List FolderList
{
get {return folderList;}
set {folderList = value;}
}
}
Properties encapsulate the private fields, provide possibilites for validation while setting. Also, you should read up on Generics (abit like templates in c++) and use List<T> instead of List to have a strongly typed collection.
However, you probably wont be able to achieve what you plan unless Setup derives from MyClass. In that case, you can use a protected field.
I'm starting to see the value of Interfaces vs. lets say an Abstract class.
Currently I'm working on a PayPal Wrapper project. We'll also be probably doing a Google Payments, BillMeLater, and Amazon wrapper. I've been asked to identify some commonalities (methods, properties, whatever) that we could use across the board, in most any Web Service SOAP Wsdl Wrapper project for any web services we do.
So as I was coding out my PayPal wrappers, I created a new class to hold Errors received back from any PayPal response:
public class ApiError
{
#region Constructors
/// <summary>
/// Disallow default instantiation.
/// </summary>
private ApiError()
{
}
internal ApiError(ErrorType error)
{
if(error.ErrorCode != null)
{
this._errorCode = error.ErrorCode;
}
}
#endregion
#region member variables
private string _errorCode = string.Empty;
private string _erorMessage = string.Empty;
#endregion
#region Properties
public string ErrorCode
{
get { return _errorCode; }
set { _errorCode = value; }
}
public string ErrorMessage
{
get { return _errorMessage; }
set { _errorMessage = value; }
}
#endregion
}
Anyway, I said hey, these ErrorMessage and ErrorCode properties are most likely going to be in every third party API. So why not create an Interface in a new project called [MyCompany].WebServices.Common and in that interface add those 2 properties. Then any class wrapper that I create that has functionality to make API proxy calls can implement this interface and then I know any of those kinds of wrapper classes in any of our web service projects will be guaranteed to have these kind of properties in them that will be impolemented and filled with any errors that come back from an API response.
And if they do, then that's great because I can then start to create some helper methods that we can use across the board if I can somehow take in a generic response object and fill the array of errors and set the property.
Anyway, my problem is, I'm new to interfaces a litte. So the error array property from above for example is of a custom type.
Well if I create interface in a seperate physical project, I can't use that custom type because it doesn't exist..it only exists so far in my PayPal wrapper project.
So then when stubbing this interface out, how would I handle this?
namespace [MyCompany].WebServices.Common
{
interface IRequest
{
public ApiError Type { get; set; } //whoops, that's a custom type that this project does not know about (ApiError)
}
}
You should consider that the ApiErrors are going to depend on the particular web service implementation. So how would a client that is using only interfaces going to use the ApiErrors if they are implementation-specific?
It can't - because this would mean that its coupled to this particular implementation.
Instead, you need to abstract away from the specific API error codes, and define your own abstract error codes.
Every Problem in Software can be Solved with Another Layer of Indirection!!! Just add another interface called IAPIError that you implement for each pay service error type.
interface IRequest
{
public IApiError Type { get; set; }
}
You could put your shared types in a separate, shared assembly: [MyCompany].WebServices.Shared
Edit
Come to think of it, you already have that. [MyCompany].WebServices.Common should be as good a place as any for your shared types. Just move it there. Or am I misunderstanding what you want to do?
The exact error numbers and messages will be very specific for each provider. Therefore, while a common interface can be made, it will not provide enough abstraction to handle errors in a meaningful way.
I'd add another abstraction by defining the expected errors (one of which is "unknown error" as catch-all for unexpected errors) as separate class or even as set of Exceptions. Then, have each provider return or use those, which is already compatible with your application and allows you to handle common errors for all providers the same way.
Put those common types into a separate assembly, which is a pure "interface" assembly used by both the providers and the actual code using them. Therefore you'll be able to loosely couple the providers without having to add references to them in your main application (allowing you to add or modify providers without recompiling the application).