I have a winform program and a Dll that stores nested classes. One of these is a Permissions class, that basically acts as a permissions director for what can be used by whom in either the winform or the Dll.
The winform needs an instance of the Permission class, so it can direct flow of code. The Dll also needs this too.
The Dll structure simplified looks like this
Master Class
Permission Class (creates the permissions)
Worker Class (needs to know permissions)
Other Class (needs to know permissions)
End Master class
MY idea was that I would create an instance of Permission class in winform and then ‘duplicate’ it in the Dll. This way I would not have to pass the reference of the Permission class instance from the winform back to the DLL, worker class (and others). And they would be in synch if winform instance were to update.
I thought I would do this by creating a Public Shared new Permission class instance in the Master Class, but that does not work, the instance is created but does not update. Im obviously wrong here.
Is there an acceptable way of creating something like the above scenario?
EDIT --------------
Im very new to the OOP concept. The permission class uses one external variable, that is the licence key, the permission class then splits the licence into various variables, each representing a different permission for different things. So, when I create the instance of the Permission class in the Form Exe like:
Perms as new Masterclass.Permission(LicenceKey)
it creates the one instance I want to use, in the Exe, but this instance is not available in the DLL.
Based on Olivier’s suggestion, how do I structure the code to have one instance of Perms being shared in the Exe and other classes within the Masterclass? I would do it in spaghetti code as a global variable in the project and its done, but now I have OOP and DLL’s and I can’t get my (old) head around it.
Assuming that you want to have one single Permission object throughout the whole lifetime of the application shared by all assemblies, create singleton objects to share data. You can do so by declaring a Public Shared ReadOnly field (or property) and making the constructor Private, so nobody else can create another instance. This ensures that only one single object exists.
Public Class Master
Public Class Permission
Public Shared ReadOnly Instance As Permission = New Permission()
Private Sub New()
End Sub
End Class
End Class
Then you can access the permissions with
Dim p = Master.Permission.Instance
or
Master.Permission.Instance.SomeMember
Note that the nested class Permission is nested statically as declaration. The outer class acts as namespace or scope. You do not need to create an instance of the surrounding class to access the inner class. Instances of nested classes are not nested in instances of the surrounding class. I.e., instances of Master and instances of Permission exist as separate, non-nested objects.
On the other hand, if you want one Permission object (an object being an instance of a class) per Master object, you must have a Permission property in the Master class. It makes no difference whether the class declarations themselves are nested or not. Usually, you would declare them as non nested in separate vb files.
Public Class Master
Public ReadOnly Property Permissions As New Permission()
End Class
Public Class Permission
End Class
Don't duplicate any code! This code must be in one assembly only. Typically you would place it in a VB Class Library Project (this creates a DLL) and reference this project in other projects where you need the permissions.
The organisation of the assemblies is completely independent from the question of the lifetime of the objects, nesting etc.
The organisation of the assemblies only affects the availability of the declarations, not the availability of the objects and sharing of data, because all the data exists in one single memory scope at runtime.
This works only within one single Process. When you start an executable, it loads the EXE and the referenced DLL's into the same memory space. The EXE and the DLL's can therefore share objects.
However, if you start different Processes (i.e., EXE's in Windows), each of them will get its own memory space. The processes do not share their memory with other processes!
If you want to share live data between processes you must use Interprocess Communication
Seee also: Partitioning Your Code Base Through .NET Assemblies and Visual Studio Projects
Related
I have a class called Contact and one called Account
and I have a method called public static Account GetAccount(Contact c) {...}
Where is the best place to put this method? What design patterns should I be looking at?
A) With the Contact class
B) With the Account class
C) Have the method accessible in both classes
D) Somewhere else?
There are probably many good answers to your question. I'll take a stab at an answer, but it will have my personal biases baked in it.
In OOP, you generally don't see globally accessible) functions, disconnected from, but available to all classes. (Static methods might be globally available, but they are still tied to a particular class). To follow up on dkatzel's answer, a common pattern is in OOP is instance manager. You have a class or instance that provides access to a a database, file store, REST service, or some other place where Contact or Account objects are saved for future use.
You might be using a persistence framework with your Python project. Maybe something like this: https://docs.djangoproject.com/en/dev/topics/db/managers/
Some persistence frameworks create handy methods instance methods like Contact.getAccount() -- send the getAccount message to a contact and the method return the associated Account object. ...Or developers can add these sorts of convenience methods themselves.
Another kind of convenience method can live on the static side of a class. For example, the Account class could have a static getAccountForContact() method that returns a particular account for a given Contact object. This method would access the instance manager and use the information in the contact object to look up the correct account.
Usually you would not add a static method to the Contact class called getAccountForContact(). Instead, you would create an instance method on Contact called getAccount(). This method could then call Account.getAccountForContact() and pass "self" in as the parameter. (Or talk to an instance manager directly).
My guiding principle is typically DRY - do not repeat yourself. I pick the option that eliminates the most copy-and-paste code.
If you define your method in this way, it's not really connected with either of your classes. You can as well put it in a Util class:
public class AccountUtil{
public static Account getAccount(Contact c){ ... }
// you can put other methods here, e.g.
public static Contact getContact(Account a){ ... }
}
This follows the pattern of grouping static functions in utility classes like Math in Java / C#.
If you would like to bound the function to a class in a clear way, consider designing your class like this:
public class Contact{
public Account getAccount(){ ... } // returns the Account of this Contact
// other methods
}
In OOP it is generally recommended that you avoid using global functions when possible. If you want a static function anyways, I'd put it in a separate class.
It depends on how the lookup from Contact to Account happens but I would vote for putting it in a new class that uses the Repository pattern.
Repository repo = ...
Account account = repo.getAccount(contact);
That way you can have multiple Repository implemtations that look up the info from a database, or an HTTP request or internal mapping etc. and you don't have to modify the code that uses the repositories.
My vote is for a new class, especially if the function returns an existing account object. That is, if you have a collection of instances of Contact and a collection of instances of Account and this function maps one to the other, use a new class to encapsulate this mapping.
Otherwise, it probably makes sense as a method on Contact if GetAccount returns a new account filled in from a template. This would hold if GetAccount is something like a factory method for the Account class, or if the Account class is just a record type (instances of which have lifetimes which are bound to instances of Contact).
The only way I see this making sense as part of Account is if it makes sense as a constructor.
I have a Class with Shared variables on a solution that contains 3 projects. I have too a reference to the project that contains shared variables from other 2 projects (we call NoShared Projects).
I can read perfect from NoShared Projects, but the problem it's I can write on shared variables from this projects.
This is the code of the class that contains shared variables.
Public Class GlobalVariables
Public Shared Debug As Boolean = False
Public Shared Username As String = ""
Public Shared Password As String = ""
End Class
If I do this from NoShared Projects:
GlobalVariables.Debug = True
Nothing happens, the value of GlobalVariable.Debug is still False.
Any help please?
I'm using different projects because each project require differents permission of execution, like Administrator permission and other normal user permission.
If your running two programs (2 EXE's, or one Web Site one EXE for example) then Shared variables are not global between them. They are only "Shared" globally inside the same application domain (same EXE).
In this case you will need to store the value somewhere else that is global to both projects or store the value in one of the running occurances and provide a way to access it (such as .net remoting, or a web service call) to write to it in only one application space.
One other way to deal with it is to store it in a database where you can pesimistically lock a table that holds the value during updates.
I'm working with a new Windows Phone 8 App, and trying to list the contacts on the phone.
In debug mode I can see the member Id (Contact.Id) with small blue icon next to the member (not an extension) but I can't access this member in programming mode, and can't view it when typing A = Contact.Id !, and can't find any document about it event on Microsoft site I can't find the member: microsoft.phone.userdata.contact.id
what is the type of this member?
I just realized that
contact.GetHashCode()
returns the exact same number as the Id property seen in the variable window drilldown.
Not sure how reliable it is, and how reliable it will be in the future.
Id is a private/protected/internal property of the Contact class. That means that in terms of the Silverlight runtime it's a non-accessible member. And that means you won't be able to get that value at runtime. Contact.Id is out of your reach.
Silverlight respects access levels and will only let you access members in the access level for the calling code. For example, all class can invoke all public members (properties, methods, events, fields, etc) of all other classes. As another example, only classes in the same assembly can invoke internal members of classes in the same assembly. If any class outside that assembly attempt to access internal members they'll get a MemberAccessException. And as a final example if a class declares private members (e.g. private field) then only that class can access that private members. If another class attempts to access private values inside a class it'll receive a MemberAccessException.
The above is true for both runtime (Reflection) invoked members and for compile-time (hardcoded) invoked members.
I made a simple PasteBin demo example of what my code looks like: http://pastebin.com/GpDhPRVm
My actual Process object is extremely complex that includes adding collections of Tasks, Documents, Workflows, etc into a Process object and setting properties through methods, etc.
My PasteBin example is as simple as I can make it to show where things break down. Including the Process object in the CreateNewProcess method in my service (shown in code below), allows the service user to automatically "see" the Process object, properties and enumerators in their instance on the client side.
<ServiceContract()>
Public Interface ICreateProcess
<OperationContract()>
Sub CreateNewProcess(ByVal newprocess As Process)
End Interface
However, it does not allow them to use any of the methods like the 'AddTask' method (shown in PasteBin example) and it also doesn't expose the Task or TaskCollection objects. Even if I decorate the methods with DataContract, OperationContract, etc they still are not visible to the client service.
This is my major issue: I need the client service to be able to fully "build" the Process object and then pass it in to the CreateNewProcess method.
Another small note: (to avoid comments asking me about it) is that I made sure that all of my properties are simple types that are interoperable since this needs to be able to work for Java - not just .NET clients.
Ok, I figured it out with a little help from a buddy of mine.
Can't use methods at all outside the .svc service class; only properties, enums and sub objects will translate down to the client. (I figured this)
Then, instead of using a Collection, you have to use a generic List type.
So, instead of this:
Public Tasks As New TaskCollection() 'where TaskCollection inherits from Collection
I needed to do this:
Public Tasks As List(Of Task)
And the client will just have to build their own array of Tasks and assign it to the t.Tasks property.
This works like a charm now: http://pastebin.com/rt8HwsXY
I'm redesigning an old VB6 application into VB.net and there is one thing I'm not sure on the best way to do.
In the VB6 application whenever we created a new instance of a component, we would pass in the user details (user name and the like) so we new who was performing the tasks. However, no that I'm redesigning I've created some nice class designs, but I'm having to add in user details into every class and it just looks wrong.
Is there a VB.net way of doing this so my classes can just have class specific details? Some way so that if my classes need to know who is performing a task, they can get the information themselves, rather than having it passed in whenever the objects are created?
You could put the details of the current user in a class that is accessible by all class instances of your application.
One place you could consider putting it is in the MyApplication class. You could also create a module and place it there.
Could you wrap the current user details into an object, and pass the object when you create the others? They would just keep a reference, and delegate to the user object for user-specific stuff.
That seems like the obvious way?