Я создаю приложение Xamarin. Android, которое будет использовать «шаблоны», шаблон таков:
[Table("Templates")]
public class Template
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
//[TextBlob("imagesBlobbed")]
[OneToMany, Unique]
public List<TemplateImage> TemplateImages { get; set; }
public string ImagesHash { get; set; }
//public string imagesBlobbed { get; set; }
}
[Table("TemplateImages")]
public class TemplateImage
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
public string ImagesHash { get; set; }
public int Image { get; set; }
[ForeignKey(typeof(Template))]
public int TemplateId { get; set; }
}
я хочу, чтобы все объекты TemplateImages были уникальными в моей базе данных, атрибут Уникальный ничего не делает, потому что я думаю, потому что в таблице TemplateImage идентификатор автоинкремента всегда будет уникальным, независимо от того, одинаковы ли Image или ImageHa sh в 2 записях.
Я думал тогда как еще я могу быть уверен, что TemplateImages будет уникальным ( Notice : когда я говорю уникально, я имею в виду, что нет никакого другого List , который имеет точное изображение для каждого TemplateImage , в том же порядке).
Также я использовал ResourceID изображений, как изображения, что неверно, поскольку они могут измениться при каждом новом обновлении скомпилированного приложения.
Поэтому я решил сделать ха sh md5 из изображений. Единственный способ, которым я нашел способ загрузить изображения ресурсов (мои изображения - векторные. xml файлы) в Xamarin. Android - путем преобразования ресурса в растровое изображение, а затем преобразуйте растровое изображение в байт, а затем байт в md5.
А также у меня должна быть строка ha sh для элемента шаблона. поэтому я создаю md5 га sh для шаблона, объединяя все байты [] изображений в одно и затем получая его.
Я создаю этот сумасшедший код для этой работы:
public static string GetMD5Hash(byte[] content)
{
using (var md5 = MD5.Create())
{
byte[] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(BitConverter.ToString(content).Replace("-", "")));
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}
private static SQLiteConnection instance;
public static SQLiteConnection db()
{
if (instance == null)
instance = new SQLiteConnection(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TemplatesData.db"));
return instance;
}
public static void CloseConnection()
{
if (instance != null)
{
instance.Close();
instance.Dispose();
instance = null;
}
}
}
public class TemplateDB
{
public static byte[] ConcatByteList(List<byte[]> list)
{
return list
.SelectMany(a => a)
.ToArray();
}
public static Bitmap GetBitmapFromVectorDrawable(Context context, int drawableId)
{
Drawable drawable = ContextCompat.GetDrawable(context, drawableId);
if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop)
{
drawable = (DrawableCompat.Wrap(drawable)).Mutate();
}
Bitmap bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth,
drawable.IntrinsicWidth, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
drawable.Draw(canvas);
return bitmap;
}
public byte[] DrawableToByteArray(int resourceId)
{
var context = AppState.ApplicationState;
using (var bitmap = GetBitmapFromVectorDrawable(context, resourceId))
{
int size = bitmap.ByteCount;
byte[] byteArray = new byte[size];
ByteBuffer byteBuffer = ByteBuffer.Allocate(size);
bitmap.CopyPixelsToBuffer(byteBuffer);
byteBuffer.Rewind();
byteBuffer.Get(byteArray);
return byteArray;
}
}
public static void AddTemplate(int category, List<int> images)
{
var templateDB = new TemplateDB();
var imageByteList = new List<byte[]>();
foreach (int image in images)
{
imageByteList.Add(templateDB.DrawableToByteArray(image));
}
var tmpl = new Template()
{
Category = category,
};
var img1 = new TemplateImage()
{
Category = category,
Image = images[0],
ImagesHash = DatabaseHelper.GetMD5Hash(imageByteList[0]),
};
var img2 = new TemplateImage()
{
Category = category,
Image = images[1],
ImagesHash = DatabaseHelper.GetMD5Hash(imageByteList[1]),
};
var img3 = new TemplateImage()
{
Category = category,
Image = images[2],
ImagesHash = DatabaseHelper.GetMD5Hash(imageByteList[2]),
};
var img4 = new TemplateImage()
{
Category = category,
Image = images[3],
ImagesHash = DatabaseHelper.GetMD5Hash(imageByteList[3]),
};
var img5 = new TemplateImage()
{
Category = category,
Image = images[4],
ImagesHash = DatabaseHelper.GetMD5Hash(imageByteList[4]),
};
tmpl.TemplateImages = new List<TemplateImage>() { img1, img2, img3, img4, img5 };
tmpl.ImagesHash = DatabaseHelper.GetMD5Hash(ConcatByteList(imageByteList));
var result = DatabaseHelper.db().Query<TemplateImage>("Select * from Templates where ImagesHash=?", tmpl.ImagesHash);
if (result.Count == 0)
{
DatabaseHelper.db().InsertAll(tmpl.TemplateImages);
DatabaseHelper.db().Insert(tmpl);
DatabaseHelper.db().UpdateWithChildren(tmpl);
}
}
Что вдруг выдает из памяти исключение.
Подумав некоторое время о том, что я должен прекратить программирование и начать танцы живота, я думаю, что поскольку я даю в sqlite AddTemplate функцию списка ResourceIds , которые у меня есть чтобы создать вручную (не могу этого избежать), то почему бы не дать им свою собственную строку с кодом sh и сравнить ее, чтобы найти, существует ли запись?
Какой правильный подход?