Get all writeable properties of an ADLDS-Class - c#

I'm developing an application which can deal with a MS-ADLDS-Service.
Currently it is possible to create Directory-Entries and assign values to some properties.
Not a realy exciting task until this:
Im my application it's possible (it should be) to configure which properties of a class (for instance: the CN=Person class) should be assigned with values which are evaluated at runtime in my application.
Long story short:
I want to retrieve all (writeable) properties of a class. Without creating and saving a new CN=Person-Object before.
Currently i use my schemaBinding to get the Directory-classSchema-Entry of the Person-Class (CN=Person) from where i read some property-values (like "AllowedAttributesEffective", "mayContain", "AllowedAttributes") - i get the most properties by this way - but some Properties are missing! For instance the "telephoneNumber"-Property (attributeSchema: CN=Telephone-Number)
Does anybody know how to get these properties of a class? ADSI-Edit does this: when i create a new object with adsi-edit i can assign values to all possible properties before committing the new entry.
thanks a lot for any hint!
(.net code is welcome)

I have found the solution for my task!
Some of these properties are "calculated" and not persistent at the directoryentry.
So its meant to call the RefreshCache() Method and pass the needed property names as an string array.
directoryEntry.RefreshCache(new string[] { "allowedAttributesEffective",
"allowedAttributes",
"systemMayContain",
"systemMustContain" });
After that call, the properties have values....
if (directoryEntry.Properties["systemMayContain"]).Value != null)
{
/// Success
}

Related

Get value of property in nested object using only a string to navigate the object

Say i have Object1 which has a list of Object2 which has Object3, which has Property1 which i want the value of. Is it possible to have a string in my database like "Object1.Object2[0].Object3.Property1" and then somehow use that within code to navigate that object and get the value for a property i want? I am getting my object i want to navigate to from another api and i basically want to look in my database and see property1 must be > 10 and then dynamically be able navigate that object so i can see if the value in my object passes my criteria in my database. I want to be able to just use database values for this so we can add fields to our database without updating our code. Is this possible?
Yes, it is definitely possible. You'll want Object1 to be a dynamic object, so that you can access its properties using variables e.g. Object1["Object2"][0]. Then all you need is to work out a consistent format for your database strings, with your example you could split by . and use a loop to access and store each property in the result successively.
See this question for info on dynamic objects from JSON (assuming that's the format you receive it in from your API) or if you'd prefer to use reflection, this question has info about that.
I found a nuget package to do exactly what i wanted. https://github.com/Domysee/Pather.CSharp

FileHelpers - Creating a field object

I am trying to dynamically add field properties to a record class that I am also building dynamically using FileHelpers.Dynamic.DelimitedClassBuilder. I have no issues creating the class object and I currently add a field using the AddField(String) method.
As my apps grows I now have a need to declare specific field properties in various situations. So in the same sense I wanted to use FileHelpers.Dynamic.DelimitedFieldBuilder to create a field object and then pass that to my DelimitedClassBuilder object using the method AddField(DelimitedFieldBuilder).
However I am unable to instantiate a new object using FileHelpers.Dynamic.DelimitedFieldBuilder. When I issue the following code I get an error stating that DelimitedFieldBuilder does not contain a constructor that takes two arguments.
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder("ClassName", "Type");
Looking at the documentation it appears that this class does only have properties associated with it, so I am kind of stuck on how to actually implement this. It seems like it should be fairly easy but I cant seem to figure it out. Thanks for any help.
Not familiar with that functionality of file helpers; however, in the vast majority of functions/methods across .NET there is usually a way to assign properties after the class is instantiated.
Try something like this:
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder();
fb.Whatever = "ClassName";
fb.otherwhatever = "Type";
Just a stab. I have no idea if it will work or not.
The constructors of DelimitedFieldBuilder are internal so you'll run into difficulty with your approach. However AddField(String) returns a DelimitedFieldBuilder, so you might be able to use that.
It might be easier to make your own class MyFieldBuilder which calls the standard AddField(String).

Populating A New Object With Existing Objects Data

I have a service that is returning a custom object called "UserSettings" In my application I want to add more properties to the "UserSettings" object so I created a new object called "MyUserSettings" that inherits from "UserSettings" now I want to populate my new object with the existing data held in "UserSettings" and the new data I have for my new properties. I do not want to have to map each property one by one to the same property in the new object like this..
_MyUserSettings.Name=_UserSettings.Name;
Is there a way or better approach to what I am doing to populate ALL the properties of the existing object into my new object in one shot??
Yes, you can use Copy Constructor pattern. It would give you an other benefit - you do not need public property setters so object becomes immutable.
public MyUserSettings(UserSettings baseSettings)
{
// TODO: set all properties
}
Unfortunately this is the only way, however, the specific mechanism can change. There are a numerous ways (not listing them all):
Copy constructor, that takes an item and does this manual copying of fields across.
Use reflection to have a more generic mechanism of achieving the same.
Use something like AutoMapper.
They all boil down to pretty much doing the same thing.
If the UserSettings is actually a MyUserSettings then you can simply cast it:
var mySettings = (MyUserSettings)settings;
However, this will fail if UserSettings is really UserSettings.

Dynamic form with no real OOP or objects?

I am tacking a large refactor of a project, and I had asked this question to confirm/understand the direction I should go in and I think I got the answer that I wanted, which is not to throw away years worth of code. So, now begins the challenge of refactoring the code. I've been reading Martine Fowler and Martin Feathers' books, and they have a lot of insight, but I am looking for advice on the ultimate goal of where I want the application to be.
So to reiterate the application a little bit, its a dynamic forms system, with lots of validation logic and data logic between the fields. The main record that gets inserted is the set of form fields that is on the page. Another part of it is 'Actions' that you can do for a person. These 'Actions' can differ client by client, and there are hundreds of 'Actions'. There is also talk that we can somehow make an engine that can eventually take on other similar areas, where a 'person' can be something else (such as student, or employee). So I want to build something very de-coupled. We have one codebase, but different DBs for different clients. The set of form fields on the page are dynamic, but the DB is not - it is translated into the specific DB table via stored procs. So, the generic set of fields are sent to the stored proc and the stored proc then decides what to do with the fields (figure out which table it needs to go to). These tables in fact are pretty static, meaning that they are not really dynamic, and there is a certain structure to it.
What I'm struggling specifically is how to setup a good way to do the dynamic form control page. It seems majority of the logic will be in code on the UI/aspx.cs page, because its loading controls onto the webpage. Is there some way I can do this, so it is done in a streamlined fashion, so the aspx.cs page isn't 5000 lines long? I have a 'FORM' object, and one of the properties is its' 'FIELDS'. So this object is loaded up in the business layer and the Data layer, but now on the fron end, it has to loop through the FIELDS and output the controls onto the page. Also, someway to be able to control the placement would be useful, too - not sure how do get that into this model....
Also, from another point of view - how can I 'really' get this into an object-oriented-structure? Because technically, they can create forms of anything. And those form fields can represent any object. So, for example, today they can create a set of form fields, that represent a 'person' - tomorrow they can create a set of form fields that represent a 'furniture'. How can I possibly translate this to to a person or a furniture object (or should I even be trying to?). And I don't really have controls over the form fields, because they can create whatever....
Any thought process would be really helpful - thanks!
How can I possibly translate this to to a person or a furniture object
(or should I even be trying to?)
If I understand you correctly, you probably shouldn't try to convert these fields to specific objects since the nature of your application is so dynamic. If the stored procedures are capable of figuring out which combination of fields belongs to which tables, then great.
If you can change the DB schema, I would suggest coming up with something much more dynamic. Rather than have a single table for each type of dynamic object, I would create the following schema:
Object {
ID
Name
... (clientID, etc.) ...
}
Property {
ID
ObjectID
Name
DBType (int, string, object-id, etc.)
FormType ( textbox, checkbox, etc.)
[FormValidationRegex] <== optional, could be used by field controls
Value
}
If you can't change the database schema, you can still apply the following to the old system using the stored procedures and fixed tables:
Then when you read in a specific object from the database, you can loop through each of the properties and get the form type and simple add the appropriate generic form type to the page:
foreach(Property p in Object.Properties)
{
switch(p.FormType)
{
case FormType.CheckBox:
PageForm.AddField(new CheckboxFormField(p.Name, p.Value));
break;
case FormType.Email:
PageForm.AddField(new EmailFormField(p.Name, p.Value));
break;
case FormType.etc:
...
break;
}
}
Of course, I threw in a PageForm object, as well as CheckboxFormField and EmailFormField objects. The PageForm object could simply be a placeholder, and the CheckboxFormField and EmailFormField could be UserControls or ServerControls.
I would not recommend trying to control placement. Just list off each field one by one vertically. This is becoming more and more popular anyway, even with static forms who's layout can be controlled completely. Most signup forms, for example, follow this convention.
I hope that helps. If I understood your question wrong, or if you'd like further explanations, let me know.
Not sure I understand the question. But there's two toolboxes suitable for writing generic code. It's generics, and it's reflection - typically in combination.
I don't think I really understand what you're trying to do, but a method using relfection to identify all the properties of an object might look like this:
using System.Reflection;
(...)
public void VisitProperties(object subject)
{
Type subjectType = subject.GetType();
foreach (PropertyInfo info in subjectType.GetProperties()
{
object value = info.GetValue(subject, null);
Console.WriteLine("The name of the property is " + info.Name);
Console.WriteLine("The value is " + value.ToString());
}
}
You can also check out an entry on my blog where I discuss using attributes on objects in conjunction with reflection. It's actually discussing how this can be utilized to write generic UI. Not exactly what you want, but at least the same principles could be used.
http://codepatrol.wordpress.com/2011/08/19/129/
This means that you could create your own custom attributes, or use those that already exists within the .NET framework already, to describe your types. Attributes to specify rules for validation, field label, even field placement could be used.
public class Person
{
[FieldLabel("First name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(1)]
[FormRow(1)]
public string FirstName{get;set;}
[FieldLabel("Last name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(2)]
[FormRow(1)]
public string LastName{get;set;}
}
Then you'd use the method described in my blog to identify these attributes and take the apropriate action - e.g. placing them in the proper row, giving the correct label, and so forth. I won't propose how to solve these things, but at least reflection is a great and simple tool to get descriptive information about an unknown type.
I found xml invaluable for this same situation. You can build an object graph in your code to represent the form easily enough. This object graph can again be loaded/saved from a db easily.
You can turn your object graph into xml & use xslt to generate the html for display. You now also have the benefit of customising this transform for differnetn clients/versions/etc. I also store the xml in the database for performance & to give me a publish function.
You need some specific code to deal with the incoming data, as you're going to be accessing the raw request post. You need to validate the incoming data against what you think you was shown. That stops people spoofing/meddling with your forms.
I hope that all makes sense.

C# - Get property in member class using Reflection

SHORT VERSION
What's the best way to use reflection to turn something like string prop = "part1.first_name"; into a System.Reflection.PropertyInfo, so that I can use the GetValue and SetValue functions?
LONG VERSION
I'm using ASP .NET MVC to build a questionnaire for my organization. It's very long, so it's divided into several different pages. Since it's not uncommon for us to get requests like, "Can you move this question to that page, and this other question to another page," I need to build this to be pretty flexible for a junior programmer to change.
My model is a complex class (it's got five member classes that have mostly primitive-typed properties on them).
So, I access it by doing things like Model.part1.first_name or Model.part2.birth_date.
Since the same model is used on all of the pages, but not all of the questions are on every page, I have ActionAttributes that essentially clear out all of the properties that were submitted on the form except for the ones that were displayed on that page (so someone can't inject a hidden field into the form and have the value persist to the database).
I want to make sure that I only save valid field values and don't let the user proceed to the next page until the current one is entirely OK, but I also want to save the values that are valid, even if the user isn't allowed to proceed.
To do this, I have a function that takes two instances of my model class, a reference to the ModelStateDictionary, and a string[] of field names like "part1.first_name" and "part2.birth_date". That function needs to copy all of the values listed in the string array that do not have validation errors from the first (ie, form-submitted) object into the second (ie, loaded from the db) object.
As stated above, what's the best way to use reflection to turn something like "part1.first_name" into a System.Reflection.PropertyInfo, OR, is there a better way to accomplish this?
var infoParts = prop.Split('.');
var myType = Type.GetType(infoParts[0]);
var myPropertyInfo = myType.GetProperty(infoParts[1]);
Assuming "part1" is your type. Although this is very limited and very dependent on the string being in the correct format and the type being in the current scope.
I would probably handle this differently, using data. I would keep, in the database, which step each question belongs to. To render that step, I would select the questions that match that step and have a model that contains a list of question id/question pairs. Each input would be identified by the question id when posted back. To validate, simply compare the set of question ids with the expected ids for that step. This way, to change which question goes in which step is to only change the data in the database.
If you do end up going down that road, you'll need to split the string into parts and recursively or iteratively find the property on the object at each step.
PropertyInfo property = null;
Type type = questionModel.GetType();
object value = questionModel;
object previousObj = null;
foreach (var part in questionId.Split('.'))
{
property = type.GetProperty(part);
previousObj = value;
value = property.GetValue(value,null);
type = value.GetType();
}
// here, if all goes well, property should contain the correct PropertyInfo and
// value should contain that property's value...and previousObj should contain
// the object that the property references, without which it won't do you much good.

Categories