Saving a System.Type class to a variable and referencing (not instantiating) type using variable

StackOverflow https://stackoverflow.com/questions/19441122

  •  01-07-2022
  •  | 
  •  

Frage

I understand how to assign a Type Class to a variable:

Type type = ("System.Security.AccessControl.FileSecurity").GetType();

How can I then use this variable as a reference for an already instantiated object?

If I try the following:

type instance = new SomeOtherType();

I get the following error code:

The type or namespace name 'type' could not be found (are you missing a using directive or an assembly reference?)

Example:

FileSecurity fSecurity = fInfo.GetAccessControl();

I would like to be able to do:

Type sometype = ("System.Security.AccessControl.FileSecurity").GetType();
sometype mynewtype = fInfo.GetAccessControl(); 

Edit: To better explain as to why I am even trying to do this in the first place, please take a look at this code:

public static class FileFolderPermissions
{
    public static void SetFileFolderPermissions()
    {
        try
        {
            DirectoryInfo dInfo = new DirectoryInfo(@"D:\SomeFolder");
            DirectorySecurity dSecurity = dInfo.GetAccessControl();

            FileInfo fInfo = new FileInfo(@"D:\Test.txt");
            FileSecurity fSecurity = fInfo.GetAccessControl();

            dSecurity.AddAccessRule(new FileSystemAccessRule("TestAccount",
                    FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
                    PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
            dInfo.SetAccessControl(dSecurity);

            fSecurity.AddAccessRule(new FileSystemAccessRule("TestAccount",
                    FileSystemRights.FullControl, AccessControlType.Allow));
            fInfo.SetAccessControl(fSecurity);

        }
        catch
        {
            Console.WriteLine("Error.");
        }
    }
}

What I am trying to do is create a generic way to set an ACL on whether the object is a File or Directory. There is a lot of code duplication in the above code as you can see. So I have been attempting to figure out how to generically pass either "DirectoryInfo" or "FileInfo" to the above code so I don't have all of the duplication.

I had come across being able to save a Type into a variable. But most of the examples I have seen dealing with Activator have involved creating an instance of the object.

As you can see, this is not creating an instance. So this is why I was wondering, "How to generalize the FileSecurity/DirectorySecurity fSecurity/dSecurity part"?

Thanks for your help.

SOLUTION: Based on the answer provided by nawfal, here is the updated class which now works for both FileInfo and DirectoryInfo along with the code in the Main method. Note: I commented out the section dealing with throwing an exception, as I haven't yet implemented the exception.

public static class DynFileFolderPermissions
{
    public static void SetFileFolderPermissions(dynamic info, FileSystemAccessRule FileAccessRule)
    {
        // if (!(info is System.IO.FileInfo) || !(info is System.IO.DirectoryInfo))
        //    throw new System.InvalidOperationException("Incorrect Type.");

        try
        {

            var security = info.GetAccessControl();

            security.AddAccessRule(FileAccessRule);
            info.SetAccessControl(security);
        }
        catch
        {
            Console.WriteLine("Error.");
        }
    }
}

// Main
class Program
{
    static void Main(string[] args)
    {
        // Grants FullControl to user "TestUser" on file D:\Test.txt
        var fileInfo = new FileInfo(@"D:\Test.txt");
        var FileAccessRule = new FileSystemAccessRule("TestUser", FileSystemRights.FullControl, AccessControlType.Allow);
        DynFileFolderPermissions.SetFileFolderPermissions(fileInfo, FileAccessRule);

        // Grants FullControl to user "TestUser" on directory D:\Test
        var directoryInfo = new DirectoryInfo(@"D:\Test");
        var DirectoryAccessRule = new FileSystemAccessRule("TestUser", FileSystemRights.FullControl,
                    InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
                    PropagationFlags.None, AccessControlType.Allow);
        DynFileFolderPermissions.SetFileFolderPermissions(directoryInfo, DirectoryAccessRule);
    }
}
War es hilfreich?

Lösung

Even if you get the System.Type from the string name of it, you only get it typed as object and you can't call members defined on FileSystemSecurity classes. You could use generics and pass a <T> but still you will have to proceed with a bunch of reflection calls using strings which are plain ugly.

You can use rely on DLR using the dynamic keyword, much less the hassle. Though it doesn't give the benefits of compile time error checking, dynamic makes it much cleaner. At least you can see your code as it is.

public static void SetFileFolderPermissions(dynamic info)
{
    if (!(info is FileInfo) || !(info is DirectoryInfo))
        throw new explosion;

    try
    {
        var security = info.GetAccessControl();
        security.AddAccessRule(new FileSystemAccessRule(...));
        info.SetAccessControl(security);
    }
    catch
    {
        Console.WriteLine("Error.");
    }
}

You can pass either a FileInfo object or DirectoryInfo object. If your FileSystemAccessRule vary for both, then you can either pass it as a parameter, or do if-else check in the method to decide. To make your method more foolproof, you can make the method private and provide two public method overloads, like:

public static void SetFilePermissions(string path)
{
    SetFileFolderPermissions
    (
        new FileInfo(path), 
        new FileSystemAccessRule
        (
            "TestAccount", 
            FileSystemRights.FullControl, 
            AccessControlType.Allow
        )
    );
}

//so that now nobody from outside can pass any dumb object to it
static void SetFileFolderPermissions(dynamic info, FileSystemAccessRule rule)
{
    try
    {
        var security = info.GetAccessControl();
        security.AddAccessRule(rule);
        info.SetAccessControl(security);
    }
    catch
    {
        Console.WriteLine("Error.");
    }
}

public static void SetFolderPermissions(string path)
{
    SetFileFolderPermissions
    (
        new DirectoryInfo(path), 
        new FileSystemAccessRule
        (
            "TestAccount",
             FileSystemRights.FullControl,
             InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
             PropagationFlags.NoPropagateInherit,
             AccessControlType.Allow
        )
    );
}

Now you dont have to pass around the bulky access rules if its written once as a part of a method overload. But I would say its still not worth doing all this, given you lose compile time checking... Also avoid the try-catch they way you have used.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top