1

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);
    }
}
Floopsy
  • 13
  • 4
  • 5
    possible duplicate of [c# instantiate class from string](http://stackoverflow.com/questions/2247598/c-sharp-instantiate-class-from-string) EDIT: Specifically, good example with the answer: http://stackoverflow.com/a/2247606/1269654 – Chris Sinclair Oct 18 '13 at 03:34
  • 3
    You realize that your first line is equivalent to `Type type = typeof(string);`, right? – Joe White Oct 18 '13 at 03:34
  • 1
    I'm assuming something else is going on here. Why are you using reflection and not just directly calling the [`FileSecurity` constructors](http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesecurity.filesecurity.aspx)? – Chris Sinclair Oct 18 '13 at 03:35

1 Answers1

0

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.

nawfal
  • 70,104
  • 56
  • 326
  • 368
  • Thanks nawfal. For `var security`, wouldn't this implicitly create a reference of type `info` (`FileInfo` or `DirectoryInfo`)? What I actually need to do is have `security` be of Type `FileSecurity` referencing a `FileInfo` instantiated object (Or `DirectorySecurity` referencing an instantiated `DirectoryInfo` object). – Floopsy Oct 18 '13 at 17:37
  • @Floopsy no, variable `security` is rightly of type `FileSecurity` if instantiated with `FileInfo` and vice versa. `dynamic` does all that during run time. Did you run the code? – nawfal Oct 18 '13 at 17:42
  • nawfal - That is awesome! It worked! Thank you very much. I am marking your answer as correct. Also, I will post my updated code here using your solution. – Floopsy Oct 18 '13 at 18:21
  • @nawful - Thanks. Good point about maybe this not being worth the extra work. etc. Still, great solution you provided there. Any suggestions as to why I shouldn't use the try/catch blocks as I am (Trying to get more familiar with those). – Floopsy Oct 18 '13 at 20:02
  • @Floopsy Its worth the extra work because now you dont have to pass the bulky access rule object, the individual overloads will take care of it. try catch should be used to catch specific exceptions, so that you know what kind of error has occurred. Catching every single type is more a lazy/hacky way. – nawfal Oct 18 '13 at 20:19
  • @nawful Thanks for clarifying. Sorry, what I meant by the "extra work" comment was that I was agreeing with your previous statement: "_But I would say its still not worth doing all this, given you lose compile time checking_" in terms of the overall project. But that is a great use of the dynamic keyword. For example, now I can probably use this code to set permissions for registry items, etc. It opens up a lot of possibilities. – Floopsy Oct 18 '13 at 20:26
  • @Floopsy oh yes, got u now :). Yes dynamic is of great help for me where .NET hasn't implemented polymorphism (similar classes, same member names) well enough. This is one such! – nawfal Oct 18 '13 at 20:30