/********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using System.ComponentModel; using Microsoft.PowerShell; #if CORECLR using System.Reflection; #endif namespace System.Management.Automation { /// /// Implements Adapter for the COM objects. /// internal class ComAdapter : Adapter { private readonly ComTypeInfo _comTypeInfo; /// /// Constructor for the ComAdapter /// /// typeinfo for the com object we are adapting internal ComAdapter(ComTypeInfo typeinfo) { Diagnostics.Assert(typeinfo != null, "Caller to verify typeinfo is not null."); _comTypeInfo = typeinfo; } internal static string GetComTypeName(string clsid) { StringBuilder firstType = new StringBuilder("System.__ComObject"); firstType.Append("#{"); firstType.Append(clsid); firstType.Append("}"); return firstType.ToString(); } /// /// Returns the TypeNameHierarchy out of an object /// /// object to get the TypeNameHierarchy from protected override IEnumerable GetTypeNameHierarchy(object obj) { yield return GetComTypeName(_comTypeInfo.Clsid); foreach (string baseType in GetDotNetTypeNameHierarchy(obj)) { yield return baseType; } } /// /// Returns null if memberName is not a member in the adapter or /// the corresponding PSMemberInfo /// /// object to retrieve the PSMemberInfo from /// name of the member to be retrieved /// The PSMemberInfo corresponding to memberName from obj protected override T GetMember(object obj, string memberName) { ComProperty prop; if (_comTypeInfo.Properties.TryGetValue(memberName, out prop)) { if (prop.IsParameterized) { if (typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty))) { return new PSParameterizedProperty(prop.Name, this, obj, prop) as T; } } else if (typeof(T).IsAssignableFrom(typeof(PSProperty))) { return new PSProperty(prop.Name, this, obj, prop) as T; } } ComMethod method; if (typeof(T).IsAssignableFrom(typeof(PSMethod)) && (_comTypeInfo != null) && (_comTypeInfo.Methods.TryGetValue(memberName, out method))) { PSMethod mshMethod = new PSMethod(method.Name, this, obj, method); return mshMethod as T; } return null; } /// /// Retrieves all the members available in the object. /// The adapter implementation is encouraged to cache all properties/methods available /// in the first call to GetMember and GetMembers so that subsequent /// calls can use the cache. /// In the case of the .NET adapter that would be a cache from the .NET type to /// the public properties and fields available in that type. /// In the case of the DirectoryEntry adapter, this could be a cache of the objectClass /// to the properties available in it. /// /// object to get all the member information from /// all members in obj protected override PSMemberInfoInternalCollection GetMembers(object obj) { PSMemberInfoInternalCollection collection = new PSMemberInfoInternalCollection(); bool lookingForProperties = typeof(T).IsAssignableFrom(typeof(PSProperty)); bool lookingForParameterizedProperties = typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty)); if (lookingForProperties || lookingForParameterizedProperties) { foreach (ComProperty prop in _comTypeInfo.Properties.Values) { if (prop.IsParameterized) { if (lookingForParameterizedProperties) { collection.Add(new PSParameterizedProperty(prop.Name, this, obj, prop) as T); } } else if (lookingForProperties) { collection.Add(new PSProperty(prop.Name, this, obj, prop) as T); } } } bool lookingForMethods = typeof(T).IsAssignableFrom(typeof(PSMethod)); if (lookingForMethods) { foreach (ComMethod method in _comTypeInfo.Methods.Values) { if (collection[method.Name] == null) { PSMethod mshmethod = new PSMethod(method.Name, this, obj, method); collection.Add(mshmethod as T); } } } return collection; } /// /// Returns an array with the property attributes /// /// property we want the attributes from /// an array with the property attributes protected override AttributeCollection PropertyAttributes(PSProperty property) { return new AttributeCollection(); } /// /// Returns the value from a property coming from a previous call to DoGetProperty /// /// PSProperty coming from a previous call to DoGetProperty /// The value of the property protected override object PropertyGet(PSProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.GetValue(property.baseObject); } /// /// Sets the value of a property coming from a previous call to DoGetProperty /// /// PSProperty coming from a previous call to DoGetProperty /// value to set the property with /// instructs the adapter to convert before setting, if the adapter suports conversion protected override void PropertySet(PSProperty property, object setValue, bool convertIfPossible) { ComProperty prop = (ComProperty)property.adapterData; prop.SetValue(property.baseObject, setValue); } /// /// Returns true if the property is settable /// /// property to check /// true if the property is settable protected override bool PropertyIsSettable(PSProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.IsSettable; } /// /// Returns true if the property is gettable /// /// property to check /// true if the property is gettable protected override bool PropertyIsGettable(PSProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.IsGettable; } /// /// Returns the name of the type corresponding to the property /// /// PSProperty obtained in a previous DoGetProperty /// True if the result is for display purposes only /// the name of the type corresponding to the property protected override string PropertyType(PSProperty property, bool forDisplay) { ComProperty prop = (ComProperty)property.adapterData; return forDisplay ? ToStringCodeMethods.Type(prop.Type) : prop.Type.FullName; } /// /// get the property signature. /// /// property object whose signature we want /// string representing the signature of the property protected override string PropertyToString(PSProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.ToString(); } #region Methods /// /// Called after a non null return from GetMethodData to try to call /// the method with the arguments /// /// the non empty return from GetMethods /// the arguments to use /// the return value for the method protected override object MethodInvoke(PSMethod method, object[] arguments) { ComMethod commethod = (ComMethod)method.adapterData; return commethod.InvokeMethod(method, arguments); } /// /// Called after a non null return from GetMethodData to return the overloads /// /// the return of GetMethodData /// protected override Collection MethodDefinitions(PSMethod method) { ComMethod commethod = (ComMethod)method.adapterData; return commethod.MethodDefinitions(); } #endregion #region parameterized property /// /// Returns the name of the type corresponding to the property's value /// /// property obtained in a previous GetMember /// the name of the type corresponding to the member protected override string ParameterizedPropertyType(PSParameterizedProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.Type.FullName; } /// /// Returns true if the property is settable /// /// property to check /// true if the property is settable protected override bool ParameterizedPropertyIsSettable(PSParameterizedProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.IsSettable; } /// /// Returns true if the property is gettable /// /// property to check /// true if the property is gettable protected override bool ParameterizedPropertyIsGettable(PSParameterizedProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.IsGettable; } /// /// Called after a non null return from GetMember to get the property value /// /// the non empty return from GetMember /// the arguments to use /// the return value for the property protected override object ParameterizedPropertyGet(PSParameterizedProperty property, object[] arguments) { ComProperty prop = (ComProperty)property.adapterData; return prop.GetValue(property.baseObject, arguments); } /// /// Called after a non null return from GetMember to set the property value /// /// the non empty return from GetMember /// the value to set property with /// the arguments to use protected override void ParameterizedPropertySet(PSParameterizedProperty property, object setValue, object[] arguments) { ComProperty prop = (ComProperty)property.adapterData; prop.SetValue(property.baseObject, setValue, arguments); } /// /// Returns the string representation of the property in the object /// /// property obtained in a previous GetMember /// the string representation of the property in the object protected override string ParameterizedPropertyToString(PSParameterizedProperty property) { ComProperty prop = (ComProperty)property.adapterData; return prop.ToString(); } /// /// Called after a non null return from GetMember to return the overloads /// /// the return of GetMember protected override Collection ParameterizedPropertyDefinitions(PSParameterizedProperty property) { ComProperty prop = (ComProperty)property.adapterData; Collection returnValue = new Collection { prop.GetDefinition() }; return returnValue; } #endregion parameterized property } }