简体   繁体   中英

Switch statement between object types

I am trying to use a switch statement to declare a variable. The variable will be a different object type based on the case i send.

object savedKey = null;
    switch (type)
    {
        case "RegistrationKey":
            savedKey = db.RegistrationKey.FirstOrDefault(k => k.RegistrationKey == key);
            break;
        case "ClockKey":
            savedKey = db.ClockKey.FirstOrDefault(k => k.RegistrationKey == key);
            break;
    }

The problem I'm running into is when I try to access the columns in the model I get the message Cannot Resolve Symbol

var decSavedkey = ConCryptor.Decrypt(savedKey.RegistrationKey);

The registration key can't be found. If I declare the object type RegistrationKey savedKey = null; then I don't receive an error, but the ClockKey in my switch statement returns an error because I declared the RegistrationKey as the object.

This is how the savedKey is used

if (savedKey != null)
        {
            try
            {
                var sentKey = ConCryptor.Decrypt(key);
                var decSavedkey = ConCryptor.Decrypt(savedKey.RegistrationKey);
                var today = DateTime.Now;
                // lets validate some keys
                if (sentKey == decSavedkey && DateTime.Parse(savedKey.ExpirationDate.ToString()) >= DateTime.Parse(today.Date.ToString()))
                {
                    status = true;
                }
            }
            catch (Exception e)
            {
                status = false;
            }

        }

You need some common base-class or interface both your classes derive from/implement. As object doesn´t know anything about a RegistrationKey , your enitities returned from your database should thus be either of type Class1 or Class2 :

interface MyInterface
{
    List<Key> Keys { get; set;}
}
public class Class1 : MyInterface
{
    public List<Key> Keys { get; set;}
}
public class Class2 : MyInterface
{
    public List<Key> Keys { get; set;}
}

Now you don´t need any switch, as the instance itself knows how to resolve Key :

MyInterface instance = db.QueryFeature(...);
savedKey = instance.Keys.FirstOrDefault(k => k.RegistrationKey == key);

You could create an interface that declares the common properties of ClockKey and RegistrationKey :

public interface IKeyProps
{
    string RegistrationKey {get;set;}
    DateTime ExpirationDate {get;set;}
}

and let the both types implement it:

public class RegistrationKey : IKeyProps
{ /*...*/ }
public class CloseKey : IKeyProps
{ /*...*/ }

Then declare the savedKey variable as IKeyProps :

IKeyProps savedKey = null;
switch (type)
{
    case "RegistrationKey":
        savedKey = db.RegistrationKey.FirstOrDefault(k => k.RegistrationKey == key);
        break;
    case "ClockKey":
        savedKey = db.ClockKey.FirstOrDefault(k => k.RegistrationKey == key);
        break;
}    

// this now works as IKeyProps declares a RegistrationKey property
var decSavedkey = ConCryptor.Decrypt(savedKey.RegistrationKey);

Alternativly (if you can't change the class declarations), you could declare savedKey as dynamic . But then you loose type safety and IntelliSense support etc. And it's rather a hack than a clean solution.

只需将单词“ object”更改为该表的类型名称,或者如果类型不同,则将其更改为“ dynamic”

There's nothing inherently wrong with adding inheritance or an interface to solve this, but I would argue it's not necessary.

Create local variables for the data you will get from each DbSet item.

string registrationKey = string.Empty;
DateTime expirationDate = DateTime.Min;

switch (type)
{
    case "RegistrationKey":
        var registrationKeyItem = db.RegistrationKey.FirstOrDefault(k => k.RegistrationKey == key)
        if (registrationKeyItem != null)
        {
            registrationKey = registrationKeyItem.RegistrationKey;
            expirationDate = registrationKeyItem.ExpirationDate;
        }
        break;
    case "ClockKey":
        var clockKeyItem = db.ClockKey.FirstOrDefault(k => k.RegistrationKey == key);
        if (clockKeyItem != null)
        {
            registrationKey = clockKeyItem.RegistrationKey;
            expirationDate = clockKeyItem.ExpirationDate;
        }
        break;
}

Then call your logic using the retrieved data. Basically, keep it simple.

var sentKey = ConCryptor.Decrypt(key);
var decSavedkey = ConCryptor.Decrypt(registrationKey);
var today = DateTime.Now;
// lets validate some keys
if (sentKey == decSavedkey && 
    DateTime.Parse(expirationDate.ToString()) >= 
    DateTime.Parse(today.Date.ToString()))
{
     status = true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM