I have a reference to a user object, the Properties collection of this object will only contain properties that have values set but I need to check if a property (by name) exists for this object - I guess this would come from the schema.
I have looked at deUser.SchemaEntry, but I can't find any useful property info from this object.
Any ideas?
DirectoryEntry deUser = new DirectoryEntry(path);
foreach (var prop in deUser.Properties)
{
//if user.Properties["company"] is not set on this user then
//it will not be available here although 'company' is
//a property defined for the user class
}
//How do I get to the list of all available properties using
//deUserSchema as below
DirectoryEntry deUserSchema = deUser.SchemaEntry();
The problem turned out to be easier to solve than it appeared. In each object (DirectoryEntry) in AD there are dynamic properties named allowedAttributes and allowedAttributesEffective.
On standard retrieval by de.Attributes [], returns null. You must first force the rebuild of the object cache (de.RefreshCache) with these parameters.
My code:
public static List<string> AllAvailableProperties(this DirectoryEntry de)
{
de.RefreshCache(new string[] { "allowedAttributes" });
return de.Properties["allowedAttributes"].AsStringList();
}
If we want a list of attributes for a class, we should take any object (existing) of this class.
To list all properties try this :
foreach (var name in deUser.Properties.PropertyNames)
{
Console.WriteLine(name);
}
According to MSDN you can use DirectoryEntry.SchemaEntry to retrieve all attributes.
An entry's schema determines a list of its mandatory and optional property names.
You can use this property to find out what properties and methods are available on the associated object.
String myADSPath = "LDAP://onecity/CN=Users,DC=onecity,DC=corp,DC=fabrikam,DC=com";
// Creates an Instance of DirectoryEntry.
DirectoryEntry myDirectoryEntry=new DirectoryEntry(myADSPath, UserName, SecurelyStoredPassword);
// Gets the SchemaEntry of the ADS object.
DirectoryEntry mySchemaEntry = myDirectoryEntry.SchemaEntry;
if (string.Compare(mySchemaEntry.Name,"container") == 0)
{
foreach(DirectoryEntry myChildDirectoryEntry in myDirectoryEntry.Children)
{
//...do what you need
}
}
Related
NOTE #1: This is in Unity, so I mention a scene, if you don't know what that is, don't worry about it, it doesn't apply too much to this question.
NOTE #2: I have looked at multiple other stack overflow posts on this subject, but they were very confusing to me, and I don't have enough reputation yet to comment, so I couldn't ask for clarification on how to use the code solutions given.
I have two custom attributes that I made, AutoSave and AutoLoad, and I want to get a List of all of their data, like the name of the field, the data that the field stores, no matter the type, and the stuff that the attribute call is given, for AutoSave: a string for the file path, a string for the scene name, a enum for the save type (which stores whether or not it will save during the beginning, the end, or when a method is called with the name of this field) and an enum for the settings (which stores whether it will write over what is currently there, or add to what is there (which is a work in progress)). And for AutoLoad: a string for the file path, a string for the scene name, and a enum for the load type (which is the exact same as the AutoSave attribute).
The code that I saw that I would like to use to sort and store is this:
Type type = typeof(AutoLoad);
foreach (PropertyInfo prop in type.GetProperties())
{
var props = from p in this.GetType().GetProperties()
let attr = p.GetCustomAttributes(typeof(AutoLoad), true)
where attr.Length == 1
select new { Property = p, Attribute = attr.First() as AutoLoad };
}
I am not sure if this is right, and I dont know how to implement, sort and store this data. If I am reading this properly, this is LINQ querying, which I am not familiar with. And I am brand new to Attributes, so if I am missing something, please let me know, and an explanation of how this code works would be nice as well.
I would store these in 6 Dictionary<string, List<WhateverTypeICanStoreTheseAs>>, the string being the scene name, the List being a list of every of this data that has that particular scene name attached. 3 dictionaries for saving, 3 for loading, each one having 1 dictionary for the beginning, 1 for the custom times, and 1 for the end. If there is a better way to store this data, please let me know!
If anyone is familiar with attributes, thanks for the help!
EDIT:
Here is my current implementation of the above code, it returns nothing when calling ToString, and returns 1 when checking outer count, and returns 0 when checking inner count.:
public static List<List<AutoSType>> GetAllOfAttribute()
{
Type type = typeof(AutoSave);
List<List<AutoSType>> objs = new List<List<AutoSType>>();
foreach (PropertyInfo prop in type.GetProperties())
{
var props = from p in prop.GetType().GetProperties()
let attr = p.GetCustomAttributes(typeof(AutoSave), true)
where attr.Length == 1
select new AutoSType { Property = p, Attribute = attr.First() as AutoSave };
objs.Add(props.ToList());
}
return objs;
}
Using the method:
List<List<AutoSType>> autoSObjs = AutoSave.GetAllOfAttribute();
Debug.Log(autoSObjs.Count);
if(autoSObjs.Count > 0)
{
Debug.Log(autoSObjs[0].Count);
}
foreach(List<AutoSType> a in autoSObjs)
{
foreach(AutoSType b in a)
{
string temp = b.Attribute.ToString();
Debug.Log(temp);
}
}
ToString override:
public override string ToString()
{
return $"{filePath}, {sceneName}, {saveType.ToString()}, {saveSettings.ToString()}";
}
Using the attribute:
[AutoSave("", "Main", AutoSave.SaveType.Beginning, AutoSave.SaveSettings.AddTo)]
public int endDate;
[AutoSave("", "Main", AutoSave.SaveType.Beginning, AutoSave.SaveSettings.AddTo)]
public string startDay;
It sounds like you're trying to find all instances of AutoSave and do something based upon that. But look at your code.
If we translate your GetAllOfAttribute to psuedo-code we get
Get the type definition for AutoSave
Initialize a list to save our List<List<AutoSType>>
Iterate all of the properties on AutoSave (wait, why?)
For each property on autoSave, get the properties on the PropertyInfo class, but only if that property on PropertyInfo has an [AutoSave] on it (Pretty sure we just went WAY off the rails here)
Instead you want to
Get all types in your assembly
For those types, filter those to the ones that contain a property with [AutoSave] on it, then operate on that type/property.
Also, as with just about anything using reflection this is going to be resource-intensive so ensure you only run it once, or once per scene. You can possibly add a class-level attribute that it can key off of to avoid iterating properties on classes you don't want looked at like creating an [AutoSaveEnabled] you can attach to the class.
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if (type.GetCustomAttribute<AutoSaveEnabled>(true) != null)
{
foreach (PropertyInfo prop in type.GetProperties())
{
AutoSave attr = prop.GetCustomAttribute<AutoSave>(true);
if (attr != null)
{
// I found the attribute!!!
// At this point, type is the class I'm looking at, prop is the decorated property, and attr is the instance of `[AutoSave]`
}
}
}
}
I want to use the value of a property called DirFotos that is mapped to column in the database table to retrieve the photos of a product. The photos of the product will be a list of string. That list is not mapped because I will retrieve it from the file system. Is it possible to use a mapped property in the setter of a NotMapped property in C# / Entity Framework? Besides photos is returning an empty list when I perform a query using the Entity Framework. Why is the NotMapped
class Product
private List<string> _photos = new List<string>();
[Column("dir_fotos")]
public String DirFotos { get; set; }
[NotMapped]
public List<String> photos
{
get { return _fotos; }
set
{
// GetPhotos(this.dirFotos) dirFotos is null here
_photos.Add("teste1.jpg");
_photos.Add("teste2.jpg");
}
}
So in summary I have two problems, I cannot use the this.dirFotos inside the setter of the photos property (it's null) and with this static snippet photos is returning an empty list when I retrieve the products using Entity Framework.
From what I make out from the question:
You have an entity to a table which contains a Directory Path for where to find the photographs.
You want to have a list of photographs which will be loaded based on the files in that directory.
You're finding that the Directory can be #null when you try to load these photographs in the non-mapped property.
I suspect that the basic premise you have written should work, however a couple of important details. For the non-mapped Photos list, you do not need, nor should use a setter. Instead it just needs a getter:
private List<string> _photos = null;
private string _dirPhotos = null;
[Column("dir_fotos")]
public String DirPhotos
{
get { return _dirPhotos; }
set
{
if(string.Compare(_dirPhotos, value, true) != 0)
{
_dirPhotos = value;
_photos = null;
}
}
}
[NotMapped]
public List<String> photos
{
get { return _photos ?? (_photos = GetPhotos(DirPhotos) ); }
}
What's important here is that your GetPhotos starts with this assertion as well:
private List<string> GetPhotos(string dirPhotos)
{
if (string.IsNullOrEmpty(dirPhotos))
return new List<string>();
// ... load photos...
}
The key differences here:
The DirPhotos is given a variable and getter/setter. If the Directory changes we want to "reset" the List variable so that it can reload when next accessed.
The list initializes to #null as the default value. When the "getter" is called, this will check if the variable is null, and if so, call your GetPhotos method. Once that variable is set it will reuse that loaded data until the directory is changed.
The GetPhotos will return an empty list if the Directory passed in is null/empty. You will also want to ensure that your GetPhotos method asserts that any directory passed in is valid and either bubble up an exception or return an empty list. Don't return #null though as we don't want to encounter null ref exceptions down the road.
I believe the issue you were encountering was that by trying to use a Setter you could be attempting to "set" the collection before the entity has had a chance to load it's data. With this pattern where the load occurs on the getter you just load the entity like normal and access the DirPhotos after the entity has been read from the DbSet. The first access of the DirPhotos will attempt to load the photos from the file system, but just be sure to handle that the entity row may not have a directory set. (or a valid directory)
I'm trying to find several properties that aren't used anywhere in our AD environment. I don't care what the property name is as long as it isn't used.
I was attempting to do this in C# mainly so that I can explore those classes while I solved this problem, but can't seem to find a way to list all of the properties for an object. The DirectoryEntry.Properties returns a collection of set properties only (as far as I can tell).
So is it possible to view all the active (available) properties for an object or are you only able to view the ones that are currently set with a value somewhere?
EDIT: Current code...
using (var directoryObject = new DirectoryEntry("LDAP://CN=GroupCN,OU=groups,DC=domain,DC=com", "uid", "pass", AuthenticationTypes.ReadonlyServer)) {
foreach (var prop in directoryObject.Properties.PropertyNames) {
Console.WriteLine(prop.ToString() + " | " + directoryObject.Properties[prop.ToString()].Value.ToString());
}
}
Edit: Ok. So I missed the bit about all possible properties. So I will address that.
Since the DirectoryEntry object is an implementation of IDictionary, there really is no way to know what properties can be set. IDictionary will allow you to add as many custom properties as you would like to the object. The documentation for System.DirectoryServices.Property collection is here: http://msdn.microsoft.com/en-us/library/system.directoryservices.propertycollection(v=vs.100).aspx
The below will enumerate all the current properties of the results of an LDAP search. You could adapt this to find all the properties that are currently used on the objects returned in the search result.
foreach (SearchResult item in searchResultCollection)
{
foreach (string propKey in item.Properties.PropertyNames)
{
foreach (object property in item.Properties[propKey])
{
Console.WriteLine("{0} : {1}", propKey, property.ToString());
}
}
}
I'm currently about to develop a website with asp.net mvc4 and mongodb as database. As the Microsoft Membership Provider does only support SQL-DB's, I've to use another Membership Provider. I decided to use the ExtendedMongoMembership Provider. Everything worked as long as I had no additional user properties passed during the Account creation. As I tried to add some additional properties like e-mail, the functionality of the CreateUserRow function throws and exception. I've downloaded the source and try to fix it. Therefore I have to separate objects inside of objects, that seems to be the way how the necessary data is passed into the function.
public bool CreateUserRow(string userName, IDictionary<string, object> values)
{
string userTableName = "Users";
List<BsonElement> elements = new List<BsonElement>();
elements.Add(new BsonElement("UserName", userName));
elements.Add(new BsonElement("_id", GetNextSequence("user_id")));
if (values != null)
{
// Here I'm facing the problem where I have to get the property names
// and the values to add them to the elements list
// The IDictionary is unfortunately not build in the way
// propertyname,value so that I could get the entries in an easy way
}
var collection = _provider.GetCollection(userTableName);
var result = collection.Insert(new BsonDocument(elements.ToArray()));
return result.LastErrorMessage == null;
}
The IDictonary contains 4 keys named (Comparer,Count,Keys,Values), the key names and their count is fixed. The property name(s) for write to the db are stored as single objects inside of an object that is the value with the key "Keys" inside the Dictonary. The same applies to the values for the db, these are stored also inside an object that is an value with the key "Values". My problem is that I have no idea how to separate these objects. Here is an picture that shows the structure of the dictionary during the debug session.
http://i.stack.imgur.com/h4z7I.jpg
How I can access the objects inside of the objects that are stored as values?
EDIT:
Found now a way, is there a better one ?
var propnames = ((IEnumerable<object>) values["Keys"]).ToArray();
var propvalues = ((IEnumerable<object>)values["Values"]).ToArray();
dynamic test;
for (int i = 0; i < propnames.Count(); i++)
{
Type type = propvalues[i].GetType();
test = Convert.ChangeType(propvalues[i], type.UnderlyingSystemType);
//BsonValue bsonValue = test as BsonValue;
elements.Add(new BsonElement(propnames[i] as string,test ));
}
I have a custom entity in a relational database that I have mapped to the CLR via a domain model. So by using the following statement, I can pull in an entity from my database into memory via a LINQ query on the domain model, like so;
var inspection = (from i in dbContext.New_testinspectionExtensionBases
where i.New_testinspectionId == currentInspection
select i).First();
There are properties/fields on this entity that I need access to, I need to be able to determine the property/field name as well as it's value. I want to loop through these items in memory, and write out their names and values to the console.
I tried using this approach, but couldn't figure out how to correct the syntax (Nor am I sure that GetProperties is the correct method to use, GetFields wasn't returning anything for some reason so I assumed this was the way to go) but it doesn't really matter since all i need is read access to the value;
var inspectionReportFields = inspection.GetType().GetProperties();
// I called this inspectionReportfields because the entity properties correspond to
// form/report fields I'm generating from this data.
foreach (var reportField in inspectionReportFields)
{
var value = reportField.GetValue();
Console.WriteLine(reportField.Name);
Console.WriteLine(value);
}
Is there an easier way to get the property/field value when utilizing a domain model like EF or openaccess? If not, am I going about it the right way? And lastly, if so, how do I fix the syntax in the value variable declaration?
Here are some sample fields/properties from the code generated by the domain model, for reference;
private int? _new_systemGauges;
public virtual int? New_systemGauges
{
get
{
return this._new_systemGauges;
}
set
{
this._new_systemGauges = value;
}
}
private int? _new_systemAlarm ;
public virtual int? New_systemAlarm
{
get
{
return this._new_systemAlarm;
}
set
{
this._new_systemAlarm = value;
}
}
I assume that you're trying to define a general-purpose way to "dump" an object without knowing anything about its structure. If so, then you are going about things the correct way. You use reflection (GetType() and the associated Type class methods) to inspect the object and return its information.
The reason GetFields() didn't return anything is that you likely did not supply the right binding flags. In particular, if you call the overload that doesn't take any parameters, you only get back public fields; if you want private fields you need to ask for them specifically.
In your case, GetFields(BindingFlags.NonPublic) would give you back the _new_systemGauges and _new_systemAlarm fields, while GetProperties() would give you back the New_systemAlarm and New_systemAlarm properties.
The other key element you missed is that the data you are getting back is the type metadata; it defines the structure of the class, and not any particular instance. If you want to know what the value of a property for a specific instance is, you need to ask for that:
foreach (var prop in obj.GetType().GetProperties())
{
Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}
One you have one of the PropertyInfo elements from the type's metadata, you can ask for that property value on any instance of that type. It doesn't have to be the same instance that you originally used. For example:
var objs = somelist.Where(x => x.Id == 1);
foreach (var prop in objs.First().GetType().GetProperties())
{
int x = 0;
foreach (var obj in objs)
{
if (prop.PropertyType.Name.Equals("Int32"))
{
int val = (int)prop.GetValue(obj, null);
Console.WriteLine("Obj #{0}: {1} = 0x{2:x8}", x++, prop.Name, val);
}
else if (prop.PropertyType.Name.Equals("Decimal"))
{
int val = (decimal)prop.GetValue(obj, null);
Console.WriteLine("Obj #{0}: {1} = {2:c2}", x++, prop.Name, val);
}
else
{
Console.WriteLine("Obj #{0}: {1} = '{2}'", x++, prop.Name, prop.GetValue(obj, null));
}
}
}
Technically you should check the result of GetIndexParameters to see if a property is indexed or not; the null parameter to GetValue is actually an array of index values.
To convert the value you get back you can either use typecasts, or if you want to be a bit more flexible, use the Convert class's methods. The difference is, for example, if you have a short property, GetValue() will return a boxed short, which you cannot then typecast as an int; you have to unbox it to a short first. Using Convert.ToInt32() will perform all of the needed steps to get an int value out of any property that is convertible to an integer.
Converting between reference types is easier since you can just use is and as for that; those work just like you'd expect with "reflected" property values.
GetProperties indeed is the correct method.
To get rid of the compiler error, change your code to this:
var value = reportField.GetValue(inspection, null);
You need to pass the instance from which you want to obtain the value, as a PropertyInfo object is not bound to any specific class instance.
Please consider following the standard .NET naming rules.
This would lead to the following:
NewSystemAlarm instead of New_systemAlarm
newSystemAlarm or _newSystemAlarm instead of _new_systemAlarm
NewTestInspectionExtensionBases instead of New_testinspectionExtensionBases
NewTestInspectionId instead of New_testinspectionId
If you are using OpenAccess you always have the complete information about your model classes at your disposal. The information there is retrieved from your mapping which means that you needn't reflect over your classes (no overhead).
Just browse trough context.Metadata.PersistentTypes for all of your classes mapping information.